Почему Bcmath возвращает неточные результаты

У меня возникли проблемы с тем, чтобы заставить bcmath работать с биткойн-фракциями на моем сервере php 7.1, ubuntu 18. Посмотрите на следующий код

bcscale(8);
$x1 = bcsub(0.04217 ,0.00007, 8);
$x2 = 0.04217 - 0.00007 ;
dd($x1 , $x2);

Результат

"0.04217000"
0.0421

Как видите, bcmath возвращает первый операнд с добавленными к нему нулями??. Любые идеи?


person ofumbi    schedule 05.02.2019    source источник
comment
Разве это не подсказка? bcscale(8); или ,8 в bcsub()   -  person RiggsFolly    schedule 05.02.2019
comment
@RiggsFolly Почему? вычитание не производилось. это просто форматирует?   -  person ofumbi    schedule 05.02.2019
comment
Вы явно указываете использовать 8 знаков после запятой - дважды! Этот необязательный [3-й] параметр используется для установки количества цифр после запятой в результате. Если этот параметр не указан, по умолчанию будет использоваться глобальный масштаб с помощью функции bcscale() или возврат к 0, если он не был установлен. согласно документам php.net/bc-sub   -  person Qirel    schedule 05.02.2019
comment
@Qirel Да, я знаю, но результат неверный. Я ожидаю 0,0421, как показано простым вычислением php, или не менее 0,04210000. почему 7 все еще там? Просто вычитал это   -  person ofumbi    schedule 05.02.2019
comment
Возможный дубликат операций bcmath с очень маленькими числами   -  person Matt Raines    schedule 15.04.2019


Ответы (1)


Руководство немного тонкое, но параметры должны быть строками. Если вы сделаете их строками, это сработает.

bcscale(8);
$x1 = bcsub('0.04217' ,'0.00007', 8);
$x2 = 0.04217 - 0.00007 ;

echo 'x1 = '. $x1 . PHP_EOL;
echo 'x2 = '. $x2;

РЕЗУЛЬТАТ

x1 = 0.04210000
x2 = 0.0421

Тоже из мануала

Внимание! Передача значений типа float в функцию BCMath, которая ожидает строку в качестве операнда, может не дать желаемого эффекта из-за того, как PHP преобразует значения с плавающей запятой в строку, а именно из-за того, что строка может быть представлена ​​в экспоненциальном представлении (что не поддерживается BCMath). , и что десятичный разделитель зависит от локали (в то время как BCMath всегда ожидает десятичную точку).

Что касается точности,

bcscale(8);
$x1 = bcsub('0.04217' ,'0.00007', 6);
//                                ^
$x2 = 0.04217 - 0.00007 ;

echo 'x1 = '. $x1 . PHP_EOL;
echo 'x2 = '. $x2;

РЕЗУЛЬТАТ

x1 = 0.042100
x2 = 0.0421

А также

bcscale(8);
$x1 = bcsub('0.04217' ,'0.00007', 4);
//                                ^
$x2 = 0.04217 - 0.00007 ;

echo 'x1 = '. $x1 . PHP_EOL;
echo 'x2 = '. $x2;

РЕЗУЛЬТАТ

x1 = 0.0421
x2 = 0.0421
person RiggsFolly    schedule 05.02.2019
comment
Да, вы абсолютно правы, уже потерял много денег, простое изменение столбца таблицы таблицы mysql со строки на DECIMAL (16, 8) сломало все мое приложение, в чем подвох! Спасибо. - person ofumbi; 05.02.2019