Mantis Bugtracker
  

Viewing Issue Simple Details Jump to Notes ] View Advanced ] Issue History ] Print ]
ID Category Severity Reproducibility Date Submitted Last Update
0003504 [Squeak] Kernel minor always 04-26-06 04:16 04-29-06 22:54
Reporter nicolas cellier View Status public  
Assigned To
Priority normal Resolution fixed  
Status closed   Product Version 3.9
Summary 0003504: Float asInteger conversion is inexact...
Description | x |
x := (10 raisedTo: 16) asFloat.

{
"This one give correctly 0"
(x asTrueFraction - (10 raisedTo: 16)) isZero.

"This one give incorrectly -1"
(x asInteger - (10 raisedTo: 16)) isZero.

"Guilty code lie in Float>>truncated: this one give 999999999999999"
(x quo: 1073741823.0) * 1073741823 + (x rem: 1073741823.0) truncated.
}.
Additional Information Integer numbers are represented exactly in IEEE 754 floating point as long as they do not exceed the mantissa limit (53 bits in double precision).

(10 raisedTo: 16) > (2 raisedTo: 53), however, 16 trailing bits are zero...
So there is no round of error and (10 raisedTo: 16) is represented exactly.

In fact, it is ((5 raisedTo: 16) asFloat timesTwoPower: 16),
and (5 raisedTo: 16) < (2 raisedTo: 53).

Problem is located in Float>>truncated
asTrueFraction does the right job, but other branch with quo: and rem: might imply inexact arithmetic and round off error...
Attached Files  Kernel-Float-truncated-Test.1.cs [^] (819 bytes) 04-26-06 05:29
 Kernel-Float-truncated-Patch.1.cs [^] (1,031 bytes) 04-26-06 05:30

- Relationships
related to 0003510closed  In 3.9a requesting a language change leads to infinite generation of testRunners 

- Notes
(0004813 - 975 - 1074 - 1074 - 1074 - 1074 - 1074)
nicolas cellier
04-26-06 05:29

Instead of using SmallInteger maxVal (1073741823), i suggest using (SmallInteger maxVal bitShift: -1)+1 (that is 2 raisedTo: 29, or 536870912)

Since it is a power of two, float division should be exact.

I provide a TestCase and a patch.
Tested only on 1000 random numbers between 1.0e12 and 2.0e16...

No performance loss.
Note that mean penalty of using self asTrueFraction truncated would be less than two on my AMD ATHLON linux, i wonder if it would not be better to use this simpler code.

{
Time millisecondsToRun: [| r x | r := Random new. 10000 timesRepeat: [x := r next * 1.0e16 + 1.0e12. x abs < 2.0e16 ifTrue: [(x quo: 536870912.0) * 536870912 + (x rem: 536870912.0) truncated] ifFalse: [x asTrueFraction]]] .

Time millisecondsToRun: [| r | r := Random new. 10000 timesRepeat: [(r next * 1.0e16 + 1.0e12) truncated ]] .

Time millisecondsToRun: [| r | r := Random new. 10000 timesRepeat: [(r next * 1.0e16 + 1.0e12) asTrueFraction truncated]] .
}
 
(0004827 - 10 - 10 - 10 - 10 - 10 - 10)
ducasse
04-29-06 22:54

in 39-7026
 

- Issue History
Date Modified Username Field Change
04-26-06 04:16 nicolas cellier New Issue
04-26-06 05:29 nicolas cellier Note Added: 0004813
04-26-06 05:29 nicolas cellier File Added: Kernel-Float-truncated-Test.1.cs
04-26-06 05:30 nicolas cellier File Added: Kernel-Float-truncated-Patch.1.cs
04-29-06 22:54 ducasse Status new => closed
04-29-06 22:54 ducasse Note Added: 0004827
04-29-06 22:54 ducasse Resolution open => fixed
04-30-06 21:17 MarcusDenker Relationship added related to 0003510


Mantis 1.0.8[^]
Copyright © 2000 - 2007 Mantis Group
48 total queries executed.
34 unique queries executed.
Powered by Mantis Bugtracker