Задать вопрос
@webev

Почему PHP выполняет математические операции неправильно?

Здравствуйте! Выполняю простую математическую операцию и получаю следующий результат:

$format = (580000000 / 1000000000); // 0.58

var_dump($format * 100); // float(57.99999999999999)


По логике $format = 0.58, значит ответ должен быть при 0.58*100 = 58, но почему тут такой результат 57.99999999999999 ?
  • Вопрос задан
  • 7235 просмотров
Подписаться 2 Простой 2 комментария
Решения вопроса 2
Коротко - потому что IEEE 754

Выполняет он математические операции правильно, но некоторые числа компьютер просто не способен представить со 100% точностью, тк для них нужно было бы бесконечное количество памяти.

Точно также, как мы не можем записать все цифры числа 1/3 в десятичной системе, точно также и компьютер иногда не может записать все цифры в двоичной.

Если ты работаешь с деньгами, то тогда используй то, что делают все банки - представляй суммы денег не как дробные числа, а как целые. Например место 1.5 рублей записывай как 150 копеек. Запятую добавишь при выводе человеку.
btw тут в комментах пишут, что для денег тоже есть паттерн по-лучше конкретно для php.

Если при делении у тебя получилось дробное количество копеек - округляй так, как велит закон.

Если ты делаешь какие-то математические вычисления - возможно тебе нужны рациональные числа.
Не знаю, что обычно для этого в пхп используют, но нагуглил https://github.com/webgriffe/rational
https://github.com/markrogoyski/math-php

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

Если тебе критически важна скорость, а точность - не так важна, то оставайся на IEEE754 и просто округляй то N значимых цифр (обычно больше 5 цифр мало кому нужно)
Ответ написан
Vamp
@Vamp
Потому что типом данных double нет возможности представить число 0.58. Поэтому компьютер берёт наиболее близкое к 0.58 число, которое double может выразить.

Если вам нужны точные вычисления, то следует воспользоваться специальными функциями:

$format = bcdiv("580000000", "1000000000", 2); // "0.58"

var_dump(bcmul($format, "100")); // string(2) "58"


Существует даже специальный сайт, рассказывающий о данной особенности математики чисел с плавающей запятой: https://0.30000000000000004.com/
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
@Everything_is_bad
Нет, он выполняет правильно, почти все ЯП так выполнят операции с float, гугли проблему с точностью вычислений
Ответ написан
Комментировать
@artem-dainov
Php, java, js. Boot spring, jquery, git
На сколько я помню, эта проблема не с php, эта проблема со всеми языками программирования.
Там что-то связано с процессорами и памятью.
Ответ написан
@semivi
Здесь давал развёрнутый ответ
https://www.mql5.com/ru/forum/1111/page2623#commen...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы