вычисление php float 2 десятичной точки

Еще одна проблема вычисления математики.

$a = 34.56 $b = 34.55 

$a сделать некоторый расчет, чтобы получить эту цифру

$b делает округление ближайшего 0,05, чтобы получить этот показатель

что происходит

 $c = $b - $a 

предположительно я должен быть -0.01, но я эхо из $c показывает -0.00988888888888

Я пытаюсь использовать n umber_format($c, 2) , но результат равен 0,00,

как я могу убедиться, что $a и $b – ровно 2 десятичных знака, без скрытого номера сзади.

в моем знании php number_format может только форматировать дисплей, но значение не действительно равно 2 десятичным,

Надеюсь, я смогу получить помощь отсюда. Это действительно расстроило меня.

Related of "вычисление php float 2 десятичной точки"

Попробуйте sprintf ("%.2f", $c);

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

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

 $a = 3456; $b = 3455; $c = $b - $a; sprintf ("%.2f", $c/100.0); 

Таким образом, у вас не будет ошибок округления, если вы делаете много расчетов перед печатью.

Использовать round() :

 $c = round($b - $a, 2); 

Примечание: вы также можете выбрать режим округления.

Edit: Ok Я не понимаю, что делает sprintf() , что number_format() не является:

 $c = number_format($b - $a, 2); 

против

 $c = sprintf("%.2f", $b - $a); 

?

Родной расчет:

 $a = 34.56; $b = 34.55; $c = $b - $a; // -0.010000000000005 

Работает так, как ожидалось (! Всегда используйте функции BC для вычисления реальных чисел, проблема для всех платформ на основе C):

 $a = '34.56'; $b = '34.55'; $c = bcsub($b, $a, 4); // -0.0100 

Недавно я столкнулся с этой проблемой при выполнении вычислений с помощью float. Например, у меня было 2 поплавки, которые при вычитании и форматировании имели значение -0.00.

 $floatOne = 267.58; $floatTwo = 267.58; $result = number_format($floatOne - floatTwo, 2); print $result; //printed a string -0.00 

Я сделал это:

 $result = abs($floatOne - $floatTwo);// Made the number positive print money_format('%i', $result); // printed the desired precision 0.00 

В моем решении я знаю, что floatOne никогда не будет меньше, чем floatTwo. Функция money_format определяется только в том случае, если система имеет функции strfmon, а Windows – нет.

Вы можете очень аккуратно обойти все эти проблемы, просто используя библиотеку bcmath.

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

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

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

Если кто-то дойдет до этой страницы с аналогичными проблемами, где вычитание с плавающим числом вызывает ошибку или странные значения. Я хочу объяснить эту проблему немного подробнее. Преступником являются числа с плавающей запятой. И разные операционные системы и разные версии языков программирования могут вести себя по-разному.

Чтобы проиллюстрировать проблему, я объясню, почему с помощью простого примера ниже.

Он напрямую не связан с PHP, и это не ошибка. Однако каждый программист должен знать об этой проблеме.

Эта проблема даже заняла много жизней два десятилетия назад.

25 февраля 1991 года эта проблема расчета плавающего числа в ракетном батарее MIM-104 Patriot помешала ему перехватить входящую ракету «Скад» в Дахране, Саудовская Аравия, в результате которой погибли 28 солдат из 14-го отряда офицера армии США.

Но почему это происходит?

Причина в том, что значения с плавающей запятой представляют собой ограниченную точность. Таким образом, после любой обработки значение может не иметь одинакового строкового представления. Он также включает в себя запись значения с плавающей запятой в ваш скрипт и прямую печать без каких-либо математических операций.

Простой пример:

 $a = '36'; $b = '-35.99'; echo ($a + $b); 

Вы ожидаете, что он напечатает 0.01, верно? Но он напечатает очень странный ответ, например: 0.009999999999998

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

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

Десятичные числа не представлены в двоичном виде из-за нехватки места. Итак, вы не можете выразить 1/3 точно так же, как это 0.3333333 …, правильно? Почему мы не можем представлять 0.01, поскольку двоичный номер с плавающей запятой по той же причине. 1/100 – 0,00000010100011110101110000 ….. с повторением 10100011110101110000.

Если 0,01 хранится в упрощенной и усеченной системой форме 01000111101011100001010 в двоичном формате, когда она будет переведена обратно в десятичную, она будет считана как 0,0099999 …. в зависимости от системы (64-битные компьютеры будут давать вам гораздо лучшую точность, чем 32-разрядные ). В этом случае операционная система решает, печатать ли ее, как она видит, или как сделать ее более понятным для человека способом. Таким образом, он зависит от машины, как они хотят его представлять. Но он может быть защищен на уровне языка различными способами.

Если вы отформатируете результат, echo number_format (0,009999999999998, 2); он будет печатать 0.01.

Это потому, что в этом случае вы инструктируете, как его следует читать и как вам нужна точность.