Некоторые значения с плавающей запятой должны суммироваться до нуля в PHP, но не

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

<?php $a = 128.3; $b = 140.7; $c = 12.4; echo $a-$b+$c; //2.30926389122E-14 ?> 

он отобразит «2.30926389122E-14»

Почему он не равен нулю?

 <?php $a = 112.7; $b = 125.2; $c = 12.5; echo $a-$b+$c; //0 ?> 

В чем разница между ними?

Related of "Некоторые значения с плавающей запятой должны суммироваться до нуля в PHP, но не"

PHP-документ отвечает на это лучше, чем я мог:

Числа с плавающей запятой имеют ограниченную точность. Хотя это зависит от системы, PHP обычно использует формат двойной точности IEEE 754, который даст максимальную относительную ошибку из-за округления порядка 1.11e-16. Неэлементарные арифметические операции могут приводить к большим ошибкам, и, конечно же, необходимо прообразить ошибку, когда несколько операций усугубляются.

Кроме того, рациональные числа, которые точно представлены в виде чисел с плавающей запятой в базе 10, например 0,1 или 0,7, не имеют точного представления в виде чисел с плавающей запятой в базе 2, которые используются внутри, независимо от размера мантиссы. Следовательно, они не могут быть преобразованы в их внутренние двоичные копии без небольшой потери точности. Это может привести к запутывающим результатам: например, пол ((0,1 + 0,7) * 10) обычно возвращает 7 вместо ожидаемого 8, так как внутреннее представление будет чем-то вроде 7.9999999999999991118 ….

Поэтому никогда не доверяйте действию чисел с плавающим числом до последней цифры и никогда не сравнивайте числа с плавающей запятой для равенства. Если требуется более высокая точность, доступны произвольные математические функции точности и функции gmp.

Изменить: название вопроса задано как исправить. Это просто … округлить. $val = round($val, 2);

Это не ошибка, это очень хорошо документированный феномен стандартов с плавающей точкой IEEE754.

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

Это означает, что вы не можете представлять все реальные числа, но должны обеспечивать приближения.

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

Прочитайте, что каждый компьютерный ученый должен знать о арифметике с плавающей точкой как подробный трактат (предупреждение, это может быть немного трудное чтение), или руководство по плавающей запятой имеет более мягкое введение, а также ссылку на пакет BC Math для PHP (произвольная точность арифметики), которая может быть вам полезна.