ошибка накопления - PullRequest
       16

ошибка накопления

0 голосов
/ 12 сентября 2010

У меня довольно прямой вопрос.Следующий код распечатывает градусы Цельсия и Фаренгейта.Мой вопрос, хотя о количестве повторений.Для небольшого числа, например, начиная с 0, остановитесь на 10 с шагом 1,1.После завершения цикла он напечатает правильное количество выполненных итераций.

Но для большого числа 0-11000000, при выполнении шага 1.1 будет напечатано неверное число итераций.Почему это происходит?Так как 1100000 / 1.1 должно быть около 1000001, но я получаю 990293.

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{

   float start, stop, step;
   int count = 0;

   cout << "start temperature: ";
   cin >> start;
   cout << "stop temperature: ";
   cin >> stop;
   cout << "step temperature: ";
   cin >> step;

   cout << setw(10) << "celsius" << setw(15) << "fahrenheit" << endl;
   cout << setw(25) << "celsius" << setw(15) << "fahrenheit" << endl;

   while(start <= stop)
   {
      count++;
      float c, f;
      c = (5.0/9)*(start-32);
      f = 32+(9.0/5)*start;
      cout << setw(10) << fixed << setprecision(2) << c << setw(15) << start << setw(15) << fixed << setprecision(2) << f  << " count: " << count << endl;

      start = start + step;
   }
   cout << "The program loop made " << count << " iterations." << endl;

   return 0;
}

Ответы [ 2 ]

5 голосов
/ 12 сентября 2010

Ошибка округления с плавающей точкой. По сути, значения с плавающей запятой не являются точным представлением на 100%, в каждом произведенном вами расчете есть ошибки, и по мере того, как вы неоднократно добавляете их, вы будете добавлять все больше и больше ошибок. Что вы должны сделать, это вычислить количество шагов за один раз, сохранить его в целое число, а затем зациклить это много раз.

0 голосов
/ 12 сентября 2010

Для справки, очищенная версия будет выглядеть так:

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{

   double start, stop, step;

   cout << "start temperature: ";
   cin >> start;
   cout << "stop temperature: ";
   cin >> stop;
   cout << "step temperature: ";
   cin >> step;

   cout << setw(10) << "celsius" << setw(15) << "fahrenheit" << endl;

   unsigned steps = (stop - start) / step;

   for(unsigned i = 0; i < steps; ++i)
   {
      double temp = start + i * step;
      double c = (5.0 / 9.0) * (temp - 32.0);
      double f = 32.0 + (9.0 / 5.0) * temp;
      // This is a real good example of why people hate <iostream> formatting.
      // If you want formatting that's quite different from the default, it
      // gets too verbose too fast. Using C stdio: 
      //printf("%10.2f%15.2f\n", c, f);
      cout << setw(10) << fixed << setprecision(2) << c
           << setw(15) << fixed << setprecision(2) << f << endl;
   }

   cout << "The program loop made " << steps << " iterations." << endl;

   return 0;
}

Основное преимущество этого стиля цикла состоит в том, что каждая итерация (кроме выходных данных) не зависит от порядка, поэтому ее можно развернуть и (теоретически) распараллелить.

...