[squeakdev] Re: Speeding up Float Numbers reading
nicolas cellier
ncellier at ifrance.com
Tue Mar 11 11:42:11 UTC 2008
Andreas Raab <andreas.raab <at> gmx.de> writes:
>
> nicolas cellier wrote:
> > A difference is that SqNumberParser does return the nearest floating
> > point value, while ReadStream>>nextFloat does return an approximate.
> > This explains some of the bad scores of the former which cannot avoid
> > LargeInteger arithmetic when the latter does (cases of exponent with
> > high values).
>
> Interesting. Do you have an example for this? I went to great length to
> ensure that #nextFloat answers consistent results to Float>>readFrom:
> (otherwise I could have optimized various cases even more aggressively)
> so I'd be interested in seeing cases where it differs.
>
> Test cases would probably be best but in absence of those some general
> guidance about how to create the problem would be appreciated.
>
Hi Andreas,
If you say nextFloat implementation is bit identicle, i trust you.
What i do not trust is Number class>>readFrom: to answer nearest Floating point.
It cumulates several rounding errors (see below).
An example is this one:
self assert:
((SqNumberParser parse: '1.2345678901234567980') asTrueFraction
 (12345678901234567980/10000000000000000000)) abs
<
((Number readFrom: '1.2345678901234567980') asTrueFraction
 (12345678901234567980/10000000000000000000)) abs.
You need a 3.9/3.10 image or patches from:
http://bugs.squeak.org/view.php?id=3564
http://bugs.squeak.org/view.php?id=3568
http://bugs.squeak.org/view.php?id=3512
Or you can just play with asTrueFraction:
(SqNumberParser parse: '1.2345678901234567980') asTrueFraction
storeStringBase: 16.
'(16r13C0CA428C59FB/16r10000000000000)'
(Number readFrom: '1.2345678901234567980') asTrueFraction
storeStringBase: 16.
'(16r4F03290A3167F/16r4000000000000)'
This is a one bit difference  multiply num and den by 4:
'(16r13C0CA428C59FC/16r10000000000000)'
Sure we can construct some cases with 2 bits off or more given the number of
successive inexact operations:
fraction := fractionPart asFloat
"asFloat is inexact at about 15 decimal digits"
/ (base raisedTo: aStream position  fracpos).
"10 raisedTo: is inexact if more than 23 digits
(with asFloat patch, otherwise worse), and division is inexact too"
fractionDigits := aStream position  fracpos.
value := value asFloat + fraction.
"Addition is inexact, that's already fourth
inexact operation before exponent operation"
And lastly:
baseValue * (base raisedTo: exp)
"That's two more inexact ops, implicit asFloat conversion if exponent > 23,
or negative, and Float multiply"
Nicolas
More information about the Squeakdev
mailing list
