Неверные результаты, полученные в простой арифметике с использованием php


Вот простой PHP-скрипт:

<?php
  $a = 100;
  $b = 91.51;
  $c = 8.49;

  $d = $a - $b - $c;
  echo $d;
?>

Он выводит -5.3290705182008E-15, что уродливо С незначительными изменениями следующим образом:

  $d = $a - ($b + $c);
  echo $d;
?>

Вывод равен 0, что является правильным. Почему это происходит?

Author: Raouf Athar, 2014-06-12

2 answers

Попробуйте использовать числовой формат следующим образом:

  $a = 100;

  $b = number_format(91.51, 0, ".", "." );

  $c = number_format(8.49, 0, ".", "." );

  $d = $a - $b - $c;

  echo $d;
 1
Author: user3734074, 2014-06-12 15:40:45

Математика с плавающей запятой на самом деле очень неточна. Это значение "наилучшего предположения";)

С плавающей запятой (одинарная точность) 100 - 91.51 - это не 8.49, как можно было бы ожидать, а 8.4899978638, поскольку значение 8.49 не может быть точно выражено в плавающей запятой. С двойной точностью он становится лучше, так как он равен 8,48999999999999488409, что немного ближе. Хотя все еще не совсем точно.

Возьмем следующий пример кода:

echo (100 - 91.51) . "\n";
echo number_format(100 - 91.51, 20) . "\n";

Результат, которого вы ожидали бы быть

8.49
8.49000000000000000000

Но на самом деле это так:

8.49
8.48999999999999488409

По умолчанию для печати значений с плавающей запятой используется округление до 2 знаков после запятой.

Плавающая точка - это в значительной степени компромисс. Это система числового представления, которая обеспечивает повышенное разрешение и дальность действия за счет точности. Для точности, но с ограниченным разрешением и диапазоном часто используется арифметика с фиксированной точкой. Например, если вы сохраняли значения напряжения от 0 В до 5 В и хотели получить точные измерения с разрешением 1 мкВ (т. Е. деления 0,000001В) вы можете вместо этого представить свои напряжения в микровольтах, а не в вольтах, поэтому значение 100000 на самом деле будет равно 0,1 В, а 3827498 будет 3,827498 вольт. Математика с заданным вами разрешением становится точной, однако у вас нет возможности представить 287x1036 V без наличия массивных переменных для хранения значения.

 3
Author: Majenko, 2014-06-12 15:18:50