0

Today PHP claims that 30.26 - 30.26 = -3.5527136788005E-15

My calculator (and common sense) says that it should equal 0. Both numbers being used in the calculation were taken from a MySQL database, data type is varchar(255). Taking this into account with floatval() doesn't seem to do the trick. Anybody know what's going on here?

/*  this is what the table looks like...
__________________________________________
|uid    |AccountNumber|    Total|    Paid|
__________________________________________
|51     |3255         |    30.26|   30.26|
__________________________________________
*/

$q = "SELECT Total, Paid FROM Account WHERE AccountNumber='3255';";
$r = mysqli_query($db, $q);
$vars = mysqli_fetch_array($r);

$balance = floatval($vars['Total']) - floatval($vars['Paid']);
echo $balance;

OUTPUT

-3.552713678805E-15
Typel
  • 1,109
  • 1
  • 11
  • 34
  • [Read, learn and inwardly digest](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems) – Mark Baker Apr 12 '17 at 18:48
  • So is the answer that PHP cannot perform math? I can understand if it is a difficulty imposed by hardware limitations, but had hoped higher level languages would have built in a workaround by now... – Typel Apr 12 '17 at 18:52
  • Fractional decimal numbers may not be representable in floating points so there is always a precision tradeoff involved when using floating point types. Even the PHP documentation points that out in it's documentation: http://php.net/manual/en/language.types.float.php This is not a limitation of PHP but applies to all languages allowing the use of floating point values. – Martin Ullrich Apr 12 '17 at 18:54
  • No.... first off, PHP isn't the only language that is subject to this issue; all languages that use IEEE754 for floats (which is almost every computer language that is used today) is subject to the same failing.... it's the computer equivalent of 1/3 as a decimal, which humans can't "display" without introducing imprecision – Mark Baker Apr 12 '17 at 18:55
  • Second... learn to use [round()](http://php.net/manual/en/function.round.php), [number_format()](http://php.net/manual/en/function.number-format.php) or [sprintf()](http://php.net/manual/en/function.sprintf.php) to handle displaying numbers to specified precision – Mark Baker Apr 12 '17 at 18:55
  • There are alternatives; such as working with numerics as string values via [bcmath](http://php.net/manual/en/book.bc.php) or [gmp](http://php.net/manual/en/book.gmp.php), but they're a lot less efficient... alternative languages use datatypes like packed decimal instead of IEEE754 – Mark Baker Apr 12 '17 at 18:57
  • @Mark Baker - this calculation isn't actually displayed in the application, it's part of a much larger algorithm, but I was checking each part for accuracy when this came up - is round() and number_format() generally acceptable for accounting? It worries me that somewhere down the line someone might get a bill for $0.01 that they don't actually owe, just by an accumulation of micromistakes. – Typel Apr 12 '17 at 19:05
  • Check any accounting system, they all have accounts for balancing out these miromistakes as you call them – RiggsFolly Apr 12 '17 at 19:16
  • If you're doing accounting; then it's best to work with the minimum units (ie cents rather than dollars) and only convert to dollars for display purposes; also, avoid any rounding during the calculation itself; and only ever round for display purposes... and note that the imprecision that you see in your calculation is at the 15dp point, not at 2dp.... and accountants have rules for handling these imprecisions – Mark Baker Apr 12 '17 at 19:18
  • Thanks for all the great advice and perspective. I inherited this system, too late to change to cents, but I do love that concept - next time! – Typel Apr 12 '17 at 19:41

0 Answers0