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_convers...
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