What is the size limit for numbers in LC? -- and multiplying really large numbers

Geoff Canyon gcanyon at gmail.com
Fri Sep 6 19:21:59 EDT 2013


On Fri, Sep 6, 2013 at 2:12 PM, Mark Wieder <mwieder at ahsoftware.net> wrote:

> At first glance that seems impressive, but do you have unit tests for
> this? If they're big random numbers, how do you know the answer is
> right?
>


I haven't done anything terribly thorough but:

1. I have checked each algorithm against the previous with at least a dozen
values (weakened by the fact that most of those values were strings of 9s,
since I was checking for overflows).
2. I have in all cases checked small values to see that they work.
3. I have checked the above mentioned strings of 9s to see that they
produce the correct result, because 999999...9999^2 = 9999...998000...0001
4. In response to this email I wrote a quick test that compared the result
of X * Y for 10,000 random number pairs, and found a bug :-) Turns out I
was losing leading 0s from intermediate results because of:

      put char -7 to -1 of S before R

if S is 1234, then R needs 0001234 in front of it -- unless this is the
last step, obviously.

This was causing put bigTimesN7(3,-480169303) to return -144507909, when it
should be -1440507909. So I amended the routine to:


function bigTimesN7 X,Y
   if char 1 of X is "-" then
      put "-" into leadChar
      delete char 1 of X
   end if
   if char 1 of Y is "-"  then
      if leadChar is "-" then put empty into leadChar else put "-" into
leadChar
      delete char 1 of Y
   end if
   put (6 + length(X)) div 7 * 7 into XL
   put char 1 to XL - length(X) of "000000" before X
   put (6 + length(Y)) div 7 * 7 into YL
   put char 1 to YL - length(y) of "000000" before y
   repeat with N = XL + YL down to 15 step -7
      repeat with M = max(7,N - YL) to min(XL,N - 7) step 7
         add (char M - 6 to M of X) * (char N - M - 6 to N - M of Y) to S
         if S > 900000019999997 then
            add char -20 to -8 of S to Scarry
            delete char -20 to -8 of S
         end if
      end repeat
      put char -7 to -1 of ("0000000" & S) before R
      add char -20 to -8 of S to Scarry
      put char -7 to -1 of Scarry into S
      delete char -7 to -1 of Scarry
   end repeat
   put Scarry & S before R
   repeat with i = 1 to 15
      if char i of R is not "0" then exit repeat
   end repeat
   if i > 1 then delete char 1 to i - 1 of R
   return leadChar & R
end bigTimesN7

I re-ran the test routine, and now it matched 10,000 out of 10,000.

Further, I have J installed, which has its own arbitrary integer precision
math. So I had LC create some equalities to test in J:

   _1130205693993682372824769249053636054878517315x =
_39214613172841811231391033x * 28821033858276318555x
1

The 1 indicates truth. J uses an underscore for negative numbers.

   _212761062255119126378152174395218739555914717752x =
29931081010835427510229954x * _7108365453893795141788x
1

   16252484302425344360409130220272036688212554937196254254608741748014x
= 41210326672812378812736110577510887x *
394378924279374110323599616495522x
1

   855949301441168562394700712367072183965950192185909474168767594482496489254071079189423582502465412218076051576598820335380230586488256862521543786177091410608514801403738523023017426796605748996223246868232771548015847240714345129475528x
= 3334475101616757910712638639825532262558105533281027610787675417225717x
* 256696863931043262844895953384410981101116109864288869619472109587827174383484710510486108696955762610103731039938527183481016179810325410499297282915105364237276610984x
 1

I think I have it now. Thanks for keeping me honest!

gc



More information about the use-livecode mailing list