2015-08-28 5 views
0

Для следующего цикла я ожидал, что выход будет sum = 20e6, но выход sum = 1.67772e+07.Максимальное значение в поплавке

float sum=0.0f; 
for(i=0;i<20e6;i++) 
    sum = sum + 1.0f; 
printf("sum = %g\n", sum); 

Вопрос 1: Почемуsum быть поплавок не может содержать значения больше, чем 1.67772e07?

Вопрос 2: Если я изменяю заявление в петле, чтобы sum = sum + 1.001f; то конечное значение суммы является 2.32229e+07. Почему это различие в значении суммы?

Вопрос 3: Можем ли мы управлять этим поведением в цикле выше таким образом, что мы можем использовать поплавок для значений больших, чем 1.67772e07 пока еще увеличивающиеся на 1.0f?

+0

Что такое i? – 7VoltCrayon

+2

Поскольку числа с плавающей запятой являются злыми. Вы должны прочитать это: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – NathanOliver

+1

Вы можете проверить максимальный доступ, используя ['std :: numeric_limits '] (http: // en.cppreference.com/w/cpp/types/numeric_limits). –

ответ

8

В какой-то момент самое близкое представляемое значение до x + 1.0f равно x. После достижения этой точки из-за этой ошибки округления ваша петля не приведет к дальнейшему увеличению sum.

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

0 = 0.000e0 
    1 = 1.000e0 
    2 = 2.000e0 
    3 = 3.000e0 

...

9 = 9.000e0 
    10 = 1.000e1 
    11 = 1.100e1 

...

99 = 9.900e1 
100 = 1.000e2 
101 = 1.010e2 

...

999 = 9.990e2 
1000 = 1.000e3 
1001 = 1.001e3 

...

9999 = 9.999e3 
10000 = 1.000e4 

, и если вы добавите еще один, вы должны получить 1.0001e4, но поскольку сохранено только 4 значащих цифры, сохраненное значение равно 1.000e4, например. 10000 + 1 = 10000 в этой системе и продолжает увеличиваться, просто повторяет этот расчет навсегда без изменения результата.

Ваш код работает точно так же, за исключением того, что float использует двоичные числа с плавающей запятой, а не десятичные знаки, как это делает научная нотация. Но число значимых двоичных цифр по-прежнему ограничено, и при добавлении еще одного не меняет одну из этих значащих цифр, sum перестает увеличиваться.

Это несколько сложнее, так как при двоичном, «правильным» результат на полпути между двумя представимых чисел, поэтому округление может происходить либо вниз или вверх, в этом случае вы просили добавить 1, но на самом деле получить результат 2 выше. В любом случае, как только расстояние между представляемыми значениями станет равным 4, попытка добавить его не будет иметь никакого эффекта.

+0

Чтобы сделать мой вопрос более ясным, я отредактировал и разбил его на три вопроса, так что, пожалуйста, обращайтесь к этим вопросам? – Imran

+0

Мое объяснение уже охватывает все три ваших вопроса. –

+0

Я все еще не понимаю, почему добавочная сумма с '1.001' продолжает менять сумму после' 1.67772e07', но приращение суммы с 1.0 не так ли? – Imran

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