Intereting Posts

Плавающая точка не печатает точно

Возможный дубликат:
Проблема с плавающей точкой в ​​C

#include main() { int a,b; float f; scanf("%2d%3d%4f",&a,&b,&f); printf("%d %d %f",a,b,f); } 

Когда я запускаю эту программу и вводю 2 4 56,8, она дает выход 2 4 56.799999 ….. но я ожидал бы 2 4 56.8 …. почему это так ???

Это правильно. Числа с плавающей запятой – это приближения. Точно так же, как 0,333333333 приближается к 1/3, 56,7999999 – приблизительное значение для 56,8. Точного представления с плавающей запятой для 0,1 нет.

См. Некоторые из того, что было написано:

56.8 не является точно представимым в формате с плавающей запятой, используемом вашим компилятором C. См., Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой (1991) Дэвида Голдберга.

Все числа с плавающей запятой не могут быть сохранены как их точное значение, так как непрерывное пространство домена с плавающей запятой отображается на дискретные уровни. Например, число с плавающей запятой может быть сохранено в формате одиночной точности IEEE754 . Он сохраняет плавающее число в трех частях в 32 бит памяти. Предположим, что [a, b] – два самых близких числа с плавающей запятой, которые могут быть представлены точно в формате IEEE754, но у нас будет бесконечное число чисел с плавающей запятой между a и b , в этом случае эти числа будут аппроксимированы либо или b . Это вызывает неточность, которую вы испытываете.

Номер хранится в нормализованном формате, хотя некоторые очень маленькие числа могут быть сохранены в ненормализованном формате. Просто взгляните на документы.

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

  • знак: 0 (1 бит)
  • смещенный показатель: 10000100 (8 бит)
  • мантисса: 11000110011001100110011 (23 бит)

Теперь, если вы преобразуете это число в десятичное, вы получите

  • знак равен 0, т. е. значение положительное
  • 10000100 = 132 сумма смещения 127, поэтому показатель = 132 – 127 = 5
  • мантисса со скрытым битом 1.11000110011001100110011
  • после корректировки десятичной точки с показателем (перемещение 5 мест справа): 111000.110011001100110011
    • Целая часть: 111000 = 2 ^ 5 + 2 ^ 4 + 2 ^ 3 = 56
    • Часть фракции: .110011001100110011 = 2 ^ -1 + 2 ^ -2 + 2 ^ -5 + 2 ^ -6 + 2 ^ -9 + 2 ^ -10 + 2 ^ -13 + 2 ^ -14 + 2 ^ – 17 + 2 ^ -18 = 0,799999237

Поэтому, когда вы извлекаете значение из формата одиночной точности IEEE754, оно становится: 56.799999237, где вы сохранили 56.8

Вы можете играть с представлением IEEE754 здесь: http://www.h-schmidt.net/FloatConverter/IEEE754.html

Возможно, это связано с неточностями с плавающей запятой.