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)

Aleksey's articles

  1. Fixed Point Math in PHP with BCMath, precision loss cases

    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 bcmath can lead to wrong results, the same precision loss as when we treat double value as string

    Case 1

    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;
    

    Results are:

    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: