2010-09-12 3 views
0

У меня есть довольно простой вопрос. Следующий код выводит на печать по Цельсию и Фаренгейту. Мой вопрос, хотя о количестве раз итерации. Для небольшого числа, например. начало 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; 
} 

ответ

5

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

+1

Вместо того, чтобы выполнять 'start = start + step;' вы должны считать шаги с целым типом и вычислить значение float из номера шага: поместите 'float temp = start + step * count;' перед 'count ++ ; 'и использовать' temp' в вашей математике вместо 'start'. Также измените цикл на 'while (start + step * count <= stop)'. –

+1

* удален * после того, как мой комментарий получил ответ, прежде чем я сделал комментарий – starzdust

0

Для записи, очищенный вверх версия будет выглядеть следующим образом:

#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; 
} 

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

Смежные вопросы