Infinite precision - Addition
Cubist at aol.com
Cubist at aol.com
Wed May 25 05:39:28 EDT 2005
use-revolution at lists.runrev.com
I am unreasonably pleased with myself. Tonight, I found and cured a most
heinous bug in my InfPreAdd handler. In addition, I found a way to make that
puppy run Significantly Faster. And best of all, the speed boost *increases*
with the number of digits!
The bug: Breaking up vast numbers into smaller chunks is all well and
good, but you have to be careful when the chunks come with leading zeroes... I
will not make the mistake of *failing* to set the numberFormat appropriately in
any other handlers in the "infinite precision" suite, thank you very much!
The speed-up: Instead of breaking things up into 14-character items, I
worked with the number-strings *as* strings. See handler below for details.
Benchmarking the new version against the old: Hardware and software
environment is as it was for the timing data I posted a few days back -- 400-MHz G3
"Pismo" w/ 320 MB of RAM, MacOS 9.1, MetaCard 2.4.1 with 55 MB of RAM
allocated to it. Yeah, I didn't provide *all* this data the last time, but nothing
changed between then and now.
I generated random N-digit numbers in pairs. Each pair of numbers was fed
to the old and new InfPreAdd versions. I used the built-in milliseconds
function for timing.
For each value of N, I used 20 pairs of numbers; of the 20 resulting
times, I set aside the 4 highest and and 4 lowest numbers, and took the average of
the remaining 16 middlemost times.
How fast *is* it, already: I've included the timing data from the original
InfPreAdd version, which indicated that the bug-fix didn't slow anything down
(hooray!). Aside from that, here's the high, low, and average times I got
working with numbers of lengths from 50 digits up to 50,000.
No. of | Orig. | Corrected | Real
Digits | Vrsn. | Avg Low High | Avg Low High
=======|=======|=====================|=================
50 | 1 | 1 0 1 | 0.6 0 1
100 | 2 | 2 1 2 | 1.2 1 2
200 | 4 | 3.8 3 4 | 2.6 2 3
500 | 9 | 9.3 8 14 | 6.1 6 7
1,000 | 20 | 19.7 17 22 | 13 12 14
2,000 | 48 | 46.6 45 64 | 27 26 44
5,000 | 175 | 175 169 200 | 74 71 90
10,000 | 580 | 575 542 592 | 182 177 196
20,000 | 2270 | 2237 2159 2327 | 572 540 602
50,000 | 14300 | 14878 14711 15224 | 3489 3381 3667
And, as mentioned above, here's the new handler...
function InfPreAdd N1, N2 # standard addition -- new and improved!
set the numberFormat to "00000000000000"
put "" into Rezult
repeat
put (char (-1 * SumChunkLen) to -1 of N1) + (char (-1 * SumChunkLen) to
-1 of N2) into Fred
delete char (-1 * SumChunkLen) to -1 of N1
delete char (-1 * SumChunkLen) to -1 of N2
put ((the length of Rezult) mod SumChunkLen) into ExtraPlace
if ExtraPlace <> 0 then
put Fred + (char 1 to ExtraPlace of Rezult) into char 1 to ExtraPlace
of Rezult
else
put Fred before Rezult
end if
if (N1 = "") and (N2 = "") then exit repeat
end repeat
repeat while char 1 of Rezult = "0"
delete char 1 of Rezult
end repeat
return Rezult
end InfPreAdd
More information about the use-livecode
mailing list