Здравствуйте! Я выполняю простую математическую операцию и получаю неожиданный результат. В частности, в следующем коде: <br/> <br/> <pre><code class="php">$format = (580000000 / 1000000000); // 0.58 var_dump($format * 100); // float(57.99999999999999)</code></pre> <br/> <br/> По моему пониманию, если $format равно 0.58, то результат выражения 0.58 * 100 должен составлять 58. Почему же в результате я получаю значение 57.99999999999999?
Здравствуйте! Ошибка, которую вы наблюдаете, связана с особенностями представления чисел с плавающей запятой в компьютерах. В PHP (как и во многих других языках программирования) числа с плавающей запятой представляются в двоичной системе, что может привести к погрешностям при математических операциях. В вашем случае, когда вы выполняете деление `580000000 / 1000000000`, результат не является точным значением 0.58 в двоичной системе. Вместо этого он хранится как близкое, но неравное значение. При последующем умножении этого приближенного значения на 100 вы получите 57.99999999999999 вместо ожидаемых 58. Чтобы избежать таких проблем, вы можете использовать функции округления, такие как `round()`, чтобы получить более предсказуемый результат. Например: ```php $format = (580000000 / 1000000000); // 0.58 $result = round($format * 100); // 58 var_dump($result); // int(58) ``` В этом случае вы получите ожидаемый результат 58, так как функция `round()` округлит ваше значение до ближайшего целого числа.
Коротко - потому что IEEE 754 <br/> <br/> Выполняет он математические операции правильно, но некоторые числа компьютер просто не способен представить со 100% точностью, тк для них нужно было бы бесконечное количество памяти. <br/> <br/> Точно также, как мы не можем записать все цифры числа 1/3 в десятичной системе, точно также и компьютер иногда не может записать все цифры в двоичной. <br/> <br/> Если ты работаешь с деньгами, то тогда используй то, что делают все банки - представляй суммы денег не как дробные числа, а как целые. Например место 1.5 рублей записывай как 150 копеек. Запятую добавишь при выводе человеку. <br/> <br/> Если при делении у тебя получилось дробное количество копеек - округляй так, как велит закон. <br/> <br/> Если ты делаешь какие-то математические вычисления - возможно тебе нужны рациональные числа. <br/> Не знаю, что обычно для этого в пхп используют, но нагуглил <a href="https://github.com/webgriffe/rational" rel="nofollow">https://github.com/webgriffe/rational</a> <br/> <a href="https://github.com/markrogoyski/math-php" rel="nofollow">https://github.com/markrogoyski/math-php</a> <br/> <br/> Но в случае с целыми числами ты всё равно можешь упереться в ограничение на максимальное число, а в случае с рациональными числами ты получишь очень сильную просадку в производительности. <br/> <br/> Если тебе критически важна скорость, а точность - не так важна, то оставайся на IEEE754 и просто округляй то N значимых цифр (обычно больше 5 цифр мало кому нужно)
Потому что типом данных double нет возможности представить число 0.58. Поэтому компьютер берёт наиболее близкое к 0.58 число, которое double может выразить. <br/> <br/> Если вам нужны точные вычисления, то следует воспользоваться специальными функциями: <br/> <br/> <pre><code class="php">$format = bcdiv("580000000", "1000000000", 2); // "0.58"
var_dump(bcmul($format, "100")); // string(2) "58"</code></pre> <br/> <br/> Существует даже специальный сайт, рассказывающий о данной особенности математики чисел с плавающей запятой: <a href="https://0.30000000000000004.com/" rel="nofollow">https://0.30000000000000004.com/</a>
Нет, он выполняет правильно, почти все ЯП так выполнят операции с float, гугли проблему с точностью вычислений