2011-01-01 15 views
1

При написании функции, которая будет выполнять некоторую операцию с каждым числом в диапазоне, я столкнулся с некоторыми проблемами с неточностями с плавающей запятой. Проблему можно увидеть в коде ниже:Неточности с плавающей запятой

#include <iostream> 

using namespace std; 

int main() 
{ 
    double start = .99999, end = 1.00001, inc = .000001; 
    int steps = (end - start)/inc; 

    for(int i = 0; i <= steps; ++i) 
    { 
     cout << (start + (inc * i)) << endl; 
    } 
} 

Проблема заключается в том, что цифры приведенные выше результаты программы выглядит следующим образом:

0.99999 
0.999991 
0.999992 
0.999993 
0.999994 
0.999995 
0.999996 
0.999997 
0.999998 
0.999999 
1 
1 
1 
1 
1 
1.00001 
1.00001 
1.00001 
1.00001 
1.00001 
1.00001 

Они только кажутся правильными до первого 1. Каков правильный способ решения этой проблемы?

+5

Но есть 20 шагов в диапазоне вы дали. Здесь нет ошибки. – monkjack

+0

Вы правы, конечно; Я изменил свой вопрос, поэтому теперь он должен иметь больше смысла. – Greg

+4

Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой: http://docs.sun.com/source/806-3568/ncg_goldberg.html – tur1ng

ответ

4

Ваш выбор только выглядит неправильным из-за того, как ostream раундов по умолчанию. Вы можете установить precision, чтобы получить другой выход.

cout.precision(10); 
cout << (start + (inc * i)) << endl; 

Вот что я получить сейчас:

0.99999 
0.999991 
0.999992 
0.999993 
0.999994 
0.999995 
0.999996 
0.999997 
0.999998 
0.999999 
1 
1.000001 
1.000002 
1.000003 
1.000004 
1.000005 
1.000006 
1.000007 
1.000008 
1.000009 
1.00001 
+2

Конечно, если вы достаточно точно знаете, вы обнаружите, что двоичный FP числа не могут хранить десятичные дроби очень точно. ;) – ijw

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