Float в PHP

php Си интересное

Давно ничего не писал, сейчас есть время и желание, буду периодически что-то интересное выкладывать.

Сегодня предлагаю разобрать интересный пример на php.

Меня в своё время очень удивило поведение var_dump/echo/print*, т.к. в большинстве ЯП точность не ограничивается по умолчанию. Взяв эту задачу на вооружения как "занимательную" для собеседований, понял что пора покопаться поглубже...

<?php

$k=0.1+0.7;
var_dump($k); //return 0.8
var_dump(0.8 == $k); //return false

$res = (string)$k - json_encode($k);
print($res); //return 1.1102230246252E-16

//@see https://3v4l.org/eDAto

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

В исходном коде легко обнаружить вызываемую функцию для var_dump, например. Поиграв с EG(precision) можно, даже не открывая документацию, понять что это просто неудачно выбранная переменная, равная 14. Да, действительно так и есть, на это дело заведена хорошо расписанная бага.

Первоначальный порыв заменить php_printf был сведен к тому что надо заменить дефолтные переменные: ini_set('precision', -1);. Выкачал репозиторий, вспомнил как собирать Си-шные проекты, протестировал немного и запилил PR, но там меня сразу осадили тем что было RFC, который объясняет что переменная serialize_precision была специально модифицирована чтобы соответствовать большинству других ЯП (относительно текущего момента - недавно).

Как итог: PR подвис в неопределенном состоянии, но я достаточно аргументированно и с пруфами объяснил чем плохи такие "тонкости". С ходу несколько багов нашел в официальном трекере где люди полагались на вывод var_dump и echo, как на верный.