Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
BUG in round() function?!?
Message
General information
Forum:
Visual FoxPro
Category:
Other
Miscellaneous
Thread ID:
00871732
Message ID:
00872887
Views:
21
Hi George,

>My hypothesis was that this "bug" was caused by a limtation of the FPU to handle values greater than 14 digits.

This is true for some round errors, but not for all round errors.

NOW I DESCRIBE THE PROOF OF ROUND() HAVE A BUG.

This is necessarily long, and need attention ( my english is not fluid ).

Preface:
A) Mathematical ROUNDING() function property:
if for two numbers x,y on a data domain, x=y is true, then ROUNDING(x,n) is equal to ROUNDING(y,n)
And this is true for IEEE 754 also.

B) VFP not support exact numeric format ( is support currency, but it is out by this exame ).
C) VFP try to simulate this with IEEE floating point with a number of decimals.

Result is : VFP maximize the worst computation
- VFP not support native IEEE 754 computation well
- VFP not support a exact computation.

Analysis, to proof that VFP ROUND() have a bug:
Use 512.045 and 512.035 numbers.

These numbers not exists on IEEE 754 64bits domain, it are approximated with IEEE binary sequences.

512.045 => 0 10000001000 0000000000000101110000101000111101011100001010001111 = 0x4080005C28F5C28F

The true value of this is :
0x4080005C28F5C28F => 512.0449999999999590727384202182292938216046875

The IEEE previous and next values are :

0x4080005C28F5C28E => 512.044999999999845385900698602199554441724375
0x4080005C28F5C290 => 512.045000000000072759576141834259033201485

---

512.035 => 0 10000001000 0000000000000100011110101110000101000111101011100001 = 
0x40800047AE147AE1

The true value of this is :

0x40800047AE147AE1 =>  512.0349999999999681676854379475116729717903125

The IEEE previous and next values are :

0x40800047AE147AE0 =>  512.03499999999985448084771633148193359191
0x40800047AE147AE2 =>  512.035000000000081854523159563541412351670625

---

Round these on IEEE domain:
The exact result of ROUND(512.045E0,2) is 512.03999999999996
The exact result of ROUND(512.035E0,2) is 512.02999999999997

In-fact on SQL Server you have this results.
SELECT ROUND(512.045E0,2),ROUND(512.035E0,2)


On VFP:
? ROUND(512.045E0,2)
* print 512.05  
? ROUND(512.035E0,2)
* print 512.04 

then ROUND NOT SUPPORT IEEE rounding.

--------------

Now check when VFP try to do decimal simulation:

X10 = ROUND(512.045,10)  && the correct is 512.0450000000 ( see IEEE exact value )

VFP cannot store this on X10 ( it is a IEEE value ) exactly; 
VFP store 0x4080005C28F5C28F  IEEE approximate value and add a format 10 decimals to X10 description.

X9  = ROUND(512.045,9)    && the correct is 512.045000000 ( see IEEE exact value )

VFP store 0x4080005C28F5C28F  IEEE approximate value and add format 9 decimals to X9 description.

Now try computation:
? m.x10 , ROUND(m.x10,2) 
* print 512.0450000000    and  512.04
? m.x9   , ROUND(m.x9,2)
* print 512.045000000     and  512.05

Result is :
? m.x10 = m.x9 , ROUND(m.x10,2) = ROUND(m.x9,2)
* this print .T. and .F.
* and VFP not support Preface point A) 

You say this is correlate with IEEE approximation, but with 512.035 these problem not occur,
now repeat the process for 512.035 value:

X10 = ROUND(512.035,10)  && the correct is 512.0350000000

VFP cannot store this on X10 exactly; 
VFP store 0x40800047AE147AE1 IEEE approximate value and add format 10 decimals to X10.

X9  = ROUND(512.035,9)    && the correct is 512.035000000

VFP store 0x40800047AE147AE1 IEEE approximate value and add format 9 decimals to X9.

Result is :
? m.x10 = m.x9 , ROUND(m.x10,2) = ROUND(m.x9,2)
* this print .T. and .T. !!

If you compare IEEE 512.045  with 512.035 :

512.045  is IEEE approximated with 512.0449999999999590727384202182292938216046875

512.035  is IEEE approximated with 512.0349999999999681676854379475116729717903125

you can found a one reasonable answer to this behavior of VFP ? 

I say NO.

Then ROUND() have a bug.
SECOND POINT

Analysis of MS bug report:

http://support.microsoft.com/support/kb/articles/Q157/9/54.asp
This is correlate with IEEE intermediate computations and last bit rounding and ROUND()function :

mrate = 86.173125

* on IEEE this is 40558B147AE147AE =>  86.173124999999998863131622783839702605586796875

mhours = 24.0000

* on IEEE this is 4038000000000000 =>  24 exactly 

* IEEE result of 86.173125*24.0000 ( 2068.1550000000000 ) is 
* 0x40A0284F5C28F5C2 => 2068.1549999999997453414835035800933837743225
 
But 2068.155 on IEEE is different ( last bit carry is lose )
* 0x40A0284F5C28F5C3 => 2068.15500000000020008883439004421234129384375

Then this explain because 
 ROUND(86.173125*24.0000,2) 
And
 ROUND(2068.1550000000000,2)

return two different values, 
and this is reasonable because 
the result of IEEE 86.173125*24.0000 is < 2068.1550000000000 ,
but IEEE of 2068.155 is > 2068.1550000000000.

Then this is not a bug, but a intrinsic IEEE problem.
My final thesis is this:
VFP try to simulate decimals computation with IEEE values, but it is impossible,
VFPT can try any workaround, fixing, etc. , it can fixing ROUND() bug, but
Bad results they will be always possible.

Then VFP cannot do a correct computation procedure
(you do not confuse numerically exact with correct procedure, thanks)
on 100% of situations.

Fabio
Previous
Reply
Map
View

Click here to load this message in the networking platform