Passionate Software Engineer
Aleksey is a professional Software Engineer from Ukraine with Master's degree in Applied Math. He worked on different positions from junior frontend developer to head of development department. Now he is working in product company on Bitcoin projects and teaching Computer Science in National Technical University in Kharkov, Ukraine. He likes contributing to open source projects and to learn a new things (Coursera and Edx are his favourite places)
When dealing with fixed point numbers, you have to be very careful – especially if you develop with PHP and MySQL. In this article, obstacles and subtleties of working with the PHP BCMath extension, MySQL fixed point expression handling and persisting fixed point data from PHP to MySQL are described. Despite the occurring barriers we try to figure out how to work with fixed point numbers and not to lose a digit.
Troubles with BCMath
BCMath documentation says:
For arbitrary precision mathematics PHP offers the Binary Calculator which supports numbers of any size and precision, represented as strings.
So BCMath function parameters should be represented as strings. Passing numeric values to
bcmathcan lead to wrong results, the same precision loss as when we treat double value as string
echo bcmul(776.210000, '100', 10) . PHP_EOL; echo bcmul(776.211000, '100', 10) . PHP_EOL; echo bcmul(776.210100, '100', 10) . PHP_EOL; echo bcmul(50018850776.210000, '100', 10) . PHP_EOL; echo bcmul(50018850776.211000, '100', 10) . PHP_EOL; echo bcmul(50018850776.210100, '100', 10) . PHP_EOL;
77621.00 77621.100 77621.0100 5001885077621.00 5001885077621.100 5001885077621.00 //here we can see precision loss
Never pass numeric values to BCMath functions, only string values that represent numbers. Even when not dealing with floating points, BCMath can output strange results: