Numerics question: reading floating point constants
stéphane ducasse
ducasse at iam.unibe.ch
Sun Apr 9 10:07:36 UTC 2006
Cool I learned something today.... :)
Better than filling some ugly rtf files :).
>> This post is one for the numerics fraction. I was just in the
>> process of
>> transcribing some interesting numerical code from C to Squeak while I
>> was running into an issue with floating point constants. The code
>> that I
>> have has constants like here:
>>
>> pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461,
>> 0x1A600000 */
>>
>> but naively transcribing this into, e.g.,
>>
>> pio22 := 6.07710050630396597660e-11.
>>
>> turned out to get some of the expected results wrong. Why? Because
>> the
>> bit pattern is different, e.g., what we get is this:
>>
>> 6.07710050630396597660e-11 hex => '3DD0B4611A5FFFFF'
>>
>> Notice how the last hex digits are different.
>>
>> My question here is the following: While I can understand why
>> *printing*
>> might give different results based on the algorithm chosen (e.g.,
>> what
>> amount of error do we allow when printing floating point numbers
>> etc) is
>> it to be expected that *reading* has similar properties? In
>> particular
>> considering that, e.g.,
>>
>> (607710050630396597660 * 1.0e-31) hex => '3DD0B4611A600000'
>>
>> gives the "correct" bit pattern makes me think that there might be
>> something broken in our way of reading floating point numbers.
>>
> A tricky question, indeed.
> I do not predend to have the answers to all problems that floats
> can introduce into computer science, but I think that method
> Number class>>readRemainderOf:from:base:withSign:
> has some questionable features.
> Here is what happens when we read a constant of the form
> <intPart>.<fractionalPart>e<expPart> :
> 1. the <intPart> is read. This is a nonnegative integer
> 2. the <fractionalPart> ist read. This is also a nonnegative integer.
> 3. The<fractionalPart> is converted into a float. A floating point
> division follows to scale that value. The floating point division
> requires a second #asFloat to bring the integer value of
> (base raisedTo: aStream position - fracpos)
> into a float.
> 4. next, the <intPart> is converted into a float (this is the third
> #asFloat
> and added to the float representation of the <fractionalPart>.
> 5. Finally, the <expPart> is read. The scale factor
> (base raisedTo: <expPart> is multiplied into the result of
> step (4), this multiplication reqires again an asFloat, the forth one
> in our algorithm.
>
> Well, I really think that four calls of #asFlaot are too much.
> We introduce approximated number representations far too
> early and we do this without need.
>
> The line
>
>> (607710050630396597660 * 1.0e-31) hex => '3DD0B4611A600000'
>
> of your post clearly shows that it is possible to introduce floats
> much later in the computation
> Attached you find a proposal (for 3.9 #6713) to avoid three of the
> four
> convertions that we use now.
>
>> Obviously, in a case like mine the best way to work around this
>> problem
>> is to construct the floats from the bit patterns directly but I can't
>> stop but wonder what the impact of a subtle bug like this might be on
>> code which does *not* include the hex denotations for the relevant
>> bit
>> patterns.
>>
>> So. Is this a bug?
>>
>> Cheers,
>> - Andreas
>>
>
> So much for now, in the afternoon I will
> * read your comments
> * look into that sutff again
> * write some test cases
>
> Cheers, Boris
>
> As always, comments are very welcome
> <ReadFloatProposal.1.cs>
>
More information about the Squeak-dev
mailing list
|