[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
|