Почему мое деление поплавка на 0,00390625? - PullRequest
1 голос
/ 02 апреля 2011
float a=67107842,b=512;
float c=a/b;
printf("%lf\n",c);

Почему c 131070.000000 вместо правильного значения 131070.00390625?

Ответы [ 3 ]

9 голосов
/ 02 апреля 2011

Тип вашего компилятора float, вероятно, использует 32-битный формат IEEE 754 с одинарной точностью.

67107842 - это 26-разрядное двоичное число:

  11111111111111110000000010

Формат с одинарной точностью представляет большинство чисел как 1.x, умноженное на некоторую (положительную или отрицательную) степень двойки, где после двоичного разряда хранится 23 бита, причем подразумевается ведущий 1. (очень маленькие числа исключение).

Но 67107842 потребует 24 бита после двоичного разряда (должно быть представлено как 1.111111111111111000000001, умноженное на 2 25 ). Так как есть 23 места для хранения только 23 битов, последний 1 теряется. Таким образом, в данном случае неверно значение в a, а не деление - a фактически содержит 67107840 (11111111111111110000000000), что в точности равно 131070 * 512.

Вы можете увидеть это, если напечатаете также a:

printf("%lf %lf %lf\n", a, b, c);

1024 * дает *

67107840.000000 512.000000 131070.000000
7 голосов
/ 02 апреля 2011

Попробуйте изменить a и c на тип double, а не на float.Это даст вам лучшую точность / точность.(У чисел с плавающей запятой около 6 или около того значащих цифр; числа с двойными числами более чем вдвое.)

0 голосов
/ 02 апреля 2011

A float обычно использует 32-битное представление IEEE-754 с одинарной точностью и подходит только для примерно 6 значащих десятичных цифр.A double подходит для 15, а при поддержке 80 бит long double достигает 20 значащих цифр.

Обратите внимание, что в некоторых компиляторах нет различия между double и long double или дажевообще не поддерживается long double.

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

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