Почему значение этого плавающего элемента отличается от установленного? - PullRequest
8 голосов
/ 11 мая 2010

Почему эта программа на C выдает «неправильный» вывод?

#include<stdio.h>

void main()
{
    float f = 12345.054321;

    printf("%f", f);

    getch();
}

Выход:

12345.054688

Но вывод должен быть, 12345.054321.

Я использую VC ++ в VS2008.

Ответы [ 5 ]

10 голосов
/ 11 мая 2010

Это дает «неправильный» ответ просто потому, что не все реальные значения представляются числами с плавающей точкой (или удваиваются, в этом отношении). То, что вы получите, является приближением, основанным на базовой кодировке.

Для представления каждого действительного значения, даже между 1,0x10 -100 и 1,1x10 -100 (поистине крошечный диапазон), вам по-прежнему требуется бесконечное количество битов.

Значения IEEE754 одинарной точности имеют только 32 бита (некоторые из которых предназначены для других задач, таких как представления экспоненты и NaN / Inf) и поэтому не могут дать вам бесконечную точность. На самом деле у них есть 23 бита, что дает точность около 2 24 (есть дополнительный неявный бит) или чуть более 7 десятичных цифр (log 10 (2 24 ) примерно 7,2).

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

Перейдите на http://www.h -schmidt.net / FloatApplet / IEEE754.html и введите свой номер в поле «Десятичное представление», чтобы увидеть это в действии.

Если вам нужно более точное число, используйте двойные числа вместо чисел с плавающей запятой - они имеют удвоенное количество битов, доступных для представления значений (при условии, что ваша реализация C использует типы данных IEEE754 одинарной и двойной точности для чисел с плавающей запятой и двойной соответственно). 1026 *

Если вам нужна произвольная точность, вам нужно использовать библиотеку "bignum", такую ​​как GMP , хотя это несколько медленнее, чем у нативных типов, поэтому убедитесь, что вы понимаете компромисс.

2 голосов
/ 11 мая 2010

float s для удобства и скорости и используют двоичное представление - если вам нужна точность, используйте десятичный тип.

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

Для решения см. FAQ по десятичной арифметике : http://speleotrove.com/decimal/decifaq.html

2 голосов
/ 11 мая 2010

Десятичное число 12345.054321 не может быть точно представлено как float на вашей платформе. Результат, который вы видите, представляет собой десятичное приближение к ближайшему числу, которое можно представить как float.

0 голосов
/ 11 мая 2010

Все дело в точности. Ваш номер не может быть точно сохранен в памяти.

0 голосов
/ 11 мая 2010

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

...