Click to See Complete Forum and Search --> : Magic Number : 1645 / Integer bug ?


cyclops
06-04-2003, 12:06 PM
One of my co-workers, a Clipper-programmer, ran into a really weird bug/problem in a billing-program he wrote, after he received a complaint from one of the customers.

The software does some calculations based on orders, and generates and prints a bill automatically.
Because of strict coding-rules every single result of the calculation is declared integer.
All goes well, until the result of the calculation becomes '1645'.
When the number '1645' (without decimals) is declared integer, it returns '1644' !

First we thought it was a coding-problem, and tried several combinations of numbers to check if the formula used is not buggy. After running several tests the formula was found to be OK, but, the problem occurs again with this 'magic' number 1645.

To test if the bug is not in the Clipper-compiler, we tried the same thing with a simple PHP script, on a different PC.
And again : when 1645 is declared integer, it returns 1644...
Since both PC's have an Intel Pentium processor, we thought it could be a kind of overflow-bug in the Pentium instruction-set, so we tried the same on a PC with an AMD processor.
And again, in the PHP-script running on an AMD based PC this time, we declare 1645 as integer, and it returns, you can already guess, 1644 !?!

So it cannot be a bug in the Intel or AMD chipset, nor in the Clipper compiler, nor in PHP.

To test this problem we used following PHP-code, using the exact same calculation that generated the errornous number :


<?php
$x = 2516.70;
$y = 871.70;
$z = $x - $y;

echo "\$x = ".$x." ; \$y = ".$y."<br>";
echo "\$z = \$x - \$y = ".$z."<br>";

settype ($z ,"integer");
echo "\$z as integer becomes ".$z."<br>";
?>


The result of $x minus $y becomes $z (1645), and this displays right.
But, when we declare $z to be integer, it suddenly becomes 1644.

We searched the net to check if there is some documentation on this bug, but we did not find a single thing.
Anybody got a clue ?

goldbug
06-04-2003, 12:19 PM
I haven't yet really looked into your problem, but I must say, your avatar RULES.

NOONE CAN ESCAPE THE QUAD-LASER!

goldbug
06-04-2003, 12:39 PM
Okay, I think I have a decent guess at an explanation....

It might have to do with the floating point precision. Not sure why, but the computer might be thinking the result from the subtraction of the two (double) values is 1644.999999999999999 or something.

When the integer conversion is performed, it just chops off the decimal places. (error occurs with settype(), intval(), and casting with (int) )

Instead, try using the bcmath functions.
in this case, bcsub() will yield the proper answer, due to a slightly different handling of precision(s).

Edit:
Try adding functions that control the precision of the inital values too.
for example, using round() (or ceil(), floor()) on the initial values (or maybe the result), will "sharpen" the precision pre-conversion.

For reference:
http://www.php.net/manual/en/ref.bc.php
http://www.php.net/manual/en/language.types.float.php
(part about float precision, conversion)

cyclops
06-04-2003, 12:42 PM
hehe, even my boss cannot escape the wrath of my quad !

quad $ : mv -i /b/boss/important_files /dev/bin/null
...whoops...

thessoro
06-04-2003, 12:53 PM
i've checked myself... it's curious!!
Ohh i'll have to change all my scripts... they have the number 1645 everywhere... it's indispensable for any calculation.

goldbug
06-04-2003, 12:54 PM
yeah, or maybe...


frylock $ cat mooninites | grep 'location' && /usr/local/athf/bin/electrozap


:)

cyclops
06-05-2003, 07:44 AM
Originally posted by goldbug
Okay, I think I have a decent guess at an explanation....

It might have to do with the floating point precision. Not sure why, but the computer might be thinking the result from the subtraction of the two (double) values is 1644.999999999999999 or something.


But there are only 2 decimals, and the substraction of the formula results in a round number, so how could this be ?


When the integer conversion is performed, it just chops off the decimal places. (error occurs with settype(), intval(), and casting with (int) )

Instead, try using the bcmath functions.
in this case, bcsub() will yield the proper answer, due to a slightly different handling of precision(s).

Edit:
Try adding functions that control the precision of the inital values too.
for example, using round() (or ceil(), floor()) on the initial values (or maybe the result), will "sharpen" the precision pre-conversion.

For reference:
http://www.php.net/manual/en/ref.bc.php
http://www.php.net/manual/en/language.types.float.php
(part about float precision, conversion)

The 'bug' was first discovered in a Clipper app, and PHP makes the same 'mistake'. We added and tried several combinations of math-functions such as round() inside the Clipper-app, and even forcing Clipper to be precise with a command at the start of the program (Precise on, if I am correct) does not help.

It is a big mystery why two different program-languages make the same mistake when casting the number '1645' to be integer.

laserlight
06-05-2003, 08:53 AM
But there are only 2 decimals, and the substraction of the formula results in a round number, so how could this be ?

I dont have a CS degree (yet), but from what I see, the internal representation of a floating point number need not be the same as that number when output.

The solution is simple: use integers when dealing with money.

goldbug
06-05-2003, 09:20 AM
Originally posted by laserlight
I dont have a CS degree (yet), but from what I see, the internal representation of a floating point number need not be the same as that number when output.

The solution is simple: use integers when dealing with money.

Agreed.
One could even just use only one kind of numerical type for a certain value representation.

Mordecai
06-05-2003, 05:39 PM
Maybe Foreigner has a song about 1645? ;)

goldbug
06-05-2003, 06:35 PM
That is seriously one of THE best episodes, if not #1.

cyclops
06-08-2003, 06:22 AM
:D Thank you all for your suggestions, I guess we'll never know what is causing the error

Solution : Stricter coding when dealing with money