Best practice for PHP float usage

php

Solution

The best way is not to use BC Math but start using GMP. Just have a look on benchmark. GMP is up to 30 times faster then BC Math.

I use DECIMAL(12, 0) AND DECIMAL(27,0) and php start suck apr. at 10^19 and greater. Demo:

//PHP Version 5.3.10,  FreeBSD 8.2-RELEASE amd64

$a = pow(10, 18);
var_dump($a, $a > ($a - 1), ($a - 1) > $a, ($a - 1) == $a, ($a - 1) === $a);
// int(1000000000000000000)
// bool(true)
// bool(false)
// bool(false)
// bool(false)

$a = pow(10, 19);
var_dump($a, $a > ($a - 1), ($a - 1) > $a, ($a - 1) == $a, ($a - 1) === $a);

// double(1.0E+19)
// bool(false)
// bool(false)
// bool(true)
// bool(true)

I made `Decimal` class, here is simple implementation. Later you can implement the same interface but with native php math operations or with BC math or whatever you want. Yupp, there will be overhead for functions calls and objects creation, but we write code that other developers can read, aren't we?

P.S. Guys from PHP Secure Communications has their own implementation - Math_BigInteger, which cover all potential need, but is too heavy for my tasks.

Update: since PHP 5.6 GMP implemented internal operators overloading, so gmp resources may be used as regular numbers (mostly).

Problem

I've read the Floating-Point guide about using the float type in PHP. The answer is using the BC Math extension. Using strings can represent the float as an exact type and prevent float and integer issues. Meanwhile I haven't found any good examples on Github and this site working with the BC math extension. What is a clean way to force PHP to use strings, how to evaluate them? Especially what is the best way to use the BC Math extension with MySQL DECIMAL data types? My example test with PHP 5.4.10, the right answer is: 0.2999999999996 ``` <?php bcscale(13); $a = '0.3'; $b = '0.0000000000004'; echo $a-$b; // 0.3 echo '<br />'; echo bcsub($a, $b); // 0.2999999999996 echo '<hr />'; $a = "0.3"; $b = "0.0000000000004"; echo $a-$b; // 0.3 echo '<br />'; echo bcsub($a, $b); // 0.2999999999996 echo '<hr />'; $a = 0.3; $b = 0.0000000000004; echo $a-$b; // 0.3 echo '<br />'; echo bcsub($a, $b); // 0.3000000000000 echo '<hr />'; $a = '0.3'; $b = '0.0000000000004' + 0; echo $a-$b; // 0.3 echo '<br />'; echo bcsub($a, $b); // 0.3000000000000 echo '<hr />'; $a = (string) 0.3; $b = (string) 0.0000000000004; echo $a-$b; // 0.3 echo '<br />'; echo bcsub($a, $b); // 0.3000000000000 echo '<hr />'; $a = strval(0.3); $b = strval(0.0000000000004); echo $a-$b; // 0.3 echo '<br />'; echo bcsub($a, $b); // 0.3000000000000 ?> ```

Original source