[squeak-dev] Float storage as Double?

Levente Uzonyi leves at elte.hu
Mon Apr 26 12:10:34 UTC 2010


On Mon, 26 Apr 2010, Lawson English wrote:

> Levente Uzonyi wrote:
>> On Mon, 26 Apr 2010, Lawson English wrote:
>> 
>>> Levente Uzonyi wrote:
>>>> On Mon, 26 Apr 2010, Lawson English wrote:
>>>> 
>>>>> I've been playing around with the Mandelbrot set and I noticed that the 
>>>>> implementation using Float looked somewhat vague. After researching a 
>>>>> while, it turns out (corrections welcome) that while Float performs 
>>>>> 64-bit FP calculations, only a limited number of decimal places are 
>>>>> stored for subsequent calculations. Is there a way around this?
>>>> 
>>>> That's not true, every Float stores 64 bits. Just because some digits are 
>>>> not shown in the printString, it doesn't mean they aren't there:
>>>> 
>>>> 1.01 printString. "==> '1.01'"
>>>> 1.01 printShowingDecimalPlaces: 60. "==> 
>>>> '1.010000000000000008881784197001252323389053344726562500000000'"
>>>> 
>>> 
>>> I'm not sure what this means:
>>> 
>>> 1.4142135623730950488016887242096980785696718753769480 
>>> printShowingDecimalPlaces: 60
>>> '1.414213562373095145474621858738828450441360473632812500000000'
>> 
>> It means that your number cannot be represented accurately as a Float. 
>> Details here:
>> http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding 
>> 
>>> 
>>> 
>>>> 
>>>>> 
>>>>> is there a faster way to truncate a ScaledDecimal than the above?
>>>> 
>>>> Sure, don't convert it to strings. :) I think you shouldn't use 
>>>> ScaledDecimal at all, since it's just a combination of a fraction and 
>>>> scale. You only need the fraction. Use #truncateTo: to truncate a number.
>>> Still confused, sorry.
>>> 
>>> Even with 15 decimal places, a Float-based M set generator is going to be 
>>> inaccurate after a few levels of zoom.  Fractions don't truncate the way I 
>>> need them to.
>> 
>> How would you like them to truncate?
>> 
>> 
>> Levente
>> 
> a := (14142135623730950488016887242096980785696718753769480
> /10000000000000000000000000000000000000000000000000000)  asScaledDecimal.
>
> a asFloat ==>1.414213562373095.
>
> b:=a * a.
> b asScaledDecimal ==> 1.999999999999999999999999999999999999999999999999999.
>
> "b asFraction  ==>
> (124999999999999999999999999999999999999999999999999987064068383137630325081727067987961060813568112169
> /62500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) 
> "
>
> "The number is stored as a Fraction and all calculations are done on the 
> Fraction."
>
> b := ScaledDecimal newFromNumber: b scale: 51.
> "b  ==> 1.999999999999999999999999999999999999999999999999999s51"
> "b asFraction ==> 
> (124999999999999999999999999999999999999999999999999987064068383137630325081727067987961060813568112169
> /62500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)"
>
> b := ScaledDecimal readFrom: b asString.
> "b ==> 1.999999999999999999999999999999999999999900000000000s51"
> "b asFraction ==>
> (19999999999999999999999999999999999999999
> /10000000000000000000000000000000000000000)"

I still don't get it. Why do you convert the number to a String? The 
following method is ~20x faster:

a := 124999999999999999999999999999999999999999999999999987064068383137630325081727067987961060813568112169 / 62500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.
b := 10e-50.
a truncateTo: b "===> (199999999999999999999999999999999999999999999999999/100000000000000000000000000000000000000000000000000)"


Levente

>
>
>
>
> So for the M set generator, since I break out of the loop if things get above 
> 2, the calculations are accurate  up to 51 decimals (in this case) when I do 
> the last operation above and I don't grow my fraction to 50,000 bytes or 
> whatever.
>
> Its slower than I would like, of course.
>
> Lawson
>
>
>
>



More information about the Squeak-dev mailing list