Routines for very large numbers.
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller
Routines for very large numbers.
Hi all,
I have a test project that needs to calculate very large numbers (30-50 digit plus). I have been running into problems with the accuracy of LC manipulating these numbers as they do not come out correctly
calculated.
After much research I found out from a few posts LC's built in function does not work correctly over 15 digits and would need to use custom functions to get the accuracy I need. Below is one of the functions I have
found. I need to now create the divide-subtract and add routines. Can any one give me some pointers or pseudocode to play with many thanks.
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 have a test project that needs to calculate very large numbers (30-50 digit plus). I have been running into problems with the accuracy of LC manipulating these numbers as they do not come out correctly
calculated.
After much research I found out from a few posts LC's built in function does not work correctly over 15 digits and would need to use custom functions to get the accuracy I need. Below is one of the functions I have
found. I need to now create the divide-subtract and add routines. Can any one give me some pointers or pseudocode to play with many thanks.
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
Re: Routines for very large numbers.
Hi.
I found this from an old Hypercard function I wrote decades ago:
I wrote one for multiplication as well. I will see if I can find it.
Craig Newman
I found this from an old Hypercard function I wrote decades ago:
Code: Select all
function longAdd arg1,arg2
put 0 into carry
put abs(the length of arg1-the length of arg2) into numzeros
repeat numzeros
put "0" after leadingZeros
end repeat
if the length of arg1 >= the length of arg2 then
put the length of arg1 into index
put leadingZeros before arg2
else
put the length of arg2 into index
put leadingZeros before arg1
end if
repeat with y = index down to 1
put char y of arg1 + char y of arg2 + carry into temp
if char y of arg1 + char y of arg2 + carry > 9 then put 1 into carry else put 0 into carry
put last char of temp before accum
end repeat
if carry = 1 then put "1" before accum
return accum
end longAdd
Craig Newman
Re: Routines for very large numbers.
Thanks Craig, much appreciated.
Re: Routines for very large numbers.
I wasn't aware of this.
I work with numbers that have:
Do I need to use your special routines to manipulate these mathematically?
I work with numbers that have:
Code: Select all
a) 18 digits (includes 2 decimal points) eg: 123456789012345.12
b) 19 digits (includes 6 decimal points) eg: 123456789012.123456
-
- VIP Livecode Opensource Backer
- Posts: 10043
- Joined: Sat Apr 08, 2006 7:05 am
- Contact:
Re: Routines for very large numbers.
Interesting - try this and let me know what you get:
Code: Select all
on mouseUp
put 123456789012345.12 into t1
put 123456789012345.12 into t2
put t1 + t2 into t3
put t3 &cr& t3 / 2
end mouseUp
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn
Re: Routines for very large numbers.
I made this handler for something lost long ago in antiquity. But it should not be hard to make it work with decimals.Do I need to use your special routines to manipulate these mathematically?
Either the routine itslef can be modified to incorporate them directly, or, if I had to do it quickly, I would add the decimal portions first, keep any remaining decimal aside, and add 1 to one of the original arguments (no two decimals will ever reach "2") if a carry was created. Adding to that argument may take just a little thought, since you probably cannot add directly, but must add to the last digit or two until no further carry is engendered.
Or better, you to do a "longAdd" on the integer portion of one argument and a "1" (if a carry is needed), and then do a longAdd on the sum with the other argument, and then append the decimal from step one.
Craig
Re: Routines for very large numbers.
I just reread your question.
If you are dealing with 19 digit number, you will lose precision in about the 17th digit. It is a limitation of the engine.
Craig
If you are dealing with 19 digit number, you will lose precision in about the 17th digit. It is a limitation of the engine.
Craig
Re: Routines for very large numbers.
I get the correct answer: 123456789012345.12FourthWorld wrote:Interesting - try this and let me know what you get:Code: Select all
on mouseUp put 123456789012345.12 into t1 put 123456789012345.12 into t2 put t1 + t2 into t3 put t3 &cr& t3 / 2 end mouseUp
Also this gives the correct answer:
Code: Select all
on mouseUp
put 123456789012345.12 into t1
put 123456789012345.12 into t2
put 1000*t1 + t2 into t3
put t3 &cr& (t3-t2) / 1000
end mouseUp
Code: Select all
on mouseUp
put 123456789012345.12 into t1
put 123456789012345.12 into t2
put t1*t2 into t3
put t3 &cr& sqrt(t3)
end mouseUp
But this gives the wrong answer: 123456789012344.91
Code: Select all
on mouseUp
put 123456789012345.12 into t1
put 123456789012345.12 into t2
put t1^12 + t2 into t3
put (t3-t2)^(1/12)
end mouseUp
Code: Select all
on mouseUp
put 123456789012345.12 into t1
put 123456789012345.12 into t2
-- put t1^12 + t2 into t3
-- put (t3-t2)^(1/12)
put t1^3 + t2 into t3
put (t3-t2)^(1/3)
end mouseUp
Last edited by golive on Tue Aug 25, 2015 8:29 am, edited 4 times in total.
Re: Routines for very large numbers.
I found the multiplication routine. It is only good to about 30 digits, and uses the "longAdd" handler. I have forgotten why it will not go farther, since there is no limit to longAdd, and I have not looked at it in a long time. You need a field "display":
Code: Select all
on mouseup
ask "First Number?"
if it is an integer then put it into arg1 else exit mouseup
ask "Second Number?"
if it is an integer then put it into arg2 else exit mouseup
put the number of chars of arg1 into index
repeat with y = the number of chars of arg1 down to 1
put char y of arg2 * arg1 & addZero(index - y) & return after temp
end repeat
repeat with y = 1 to the number of lines of temp - 1
put longAdd(line y of temp,line y + 1 of temp) into line y + 1 of temp
end repeat
put last line of temp into fld "display"
end mouseup
function addZero var
repeat var
put 0 after zeros
end repeat
return zeros
end addZero
Re: Routines for very large numbers.
I used Edit to add some more examples to my post above.
See the power of 3 example.
See the power of 3 example.

Re: Routines for very large numbers.
hi, just wonder about the code to dunbarx, hope i don't mispell that username.
can the problem be that you are still using int somewhere in the multiply code?
if so, maybe it can be usefull to try some african math
can not use links because its my first post
but did find this
"Multiplication
Shortcuts were needed, and multiplication is a shortcut for addition, just as
addition is a shortcut for counting. With the Egyptian method, this principle is easy
to understand. In fact, tables were not needed in Egyptian multiplication. To
illustrate: “13 hekats of grain are taken 27 times. How many in all?”32
Although the problem was stated in concrete terms, as hekats of grain, the
numbers were thought of abstractly. The commutative law was used because it
was easier to multiply by 13 than by 27.
Start with one 27 and then continue to double, which can be done simply by
adding the number to itself.
1 27
2 54
4 108
8 216
At this point the scribe would stop because the next step would give 16, and only
13 of the 27's were wanted. Now the partial products are added to get 13 x 27.
\ 1 27 / 1 27
2 54 4 108
\ 4 108 / 8 216
\ 8 216 /
TOTAL 13 351 "
hope it makes some sense, english is not my native language, and i am pretty useless even in that
has some code to start with
can the problem be that you are still using int somewhere in the multiply code?
if so, maybe it can be usefull to try some african math
can not use links because its my first post

"Multiplication
Shortcuts were needed, and multiplication is a shortcut for addition, just as
addition is a shortcut for counting. With the Egyptian method, this principle is easy
to understand. In fact, tables were not needed in Egyptian multiplication. To
illustrate: “13 hekats of grain are taken 27 times. How many in all?”32
Although the problem was stated in concrete terms, as hekats of grain, the
numbers were thought of abstractly. The commutative law was used because it
was easier to multiply by 13 than by 27.
Start with one 27 and then continue to double, which can be done simply by
adding the number to itself.
1 27
2 54
4 108
8 216
At this point the scribe would stop because the next step would give 16, and only
13 of the 27's were wanted. Now the partial products are added to get 13 x 27.
\ 1 27 / 1 27
2 54 4 108
\ 4 108 / 8 216
\ 8 216 /
TOTAL 13 351 "
hope it makes some sense, english is not my native language, and i am pretty useless even in that

has some code to start with
Code: Select all
on mouseUp
global myDouble
local myNumb
/*
need 3 field
field "data" is a scrollling field
field t1 and t2 is the factors to multiply
*/
put empty into field "data"
put 1 into myDouble
repeat until myDouble > field "t2"
if the number of lines of field "data" = 0 then
put field "t1" into myNumb
put myDouble & " " & myNumb & cr after field "data"
put longAdd(myNumb,myNumb) into myNumb
else
put longAdd(myNumb,myNumb) into myNumb
put myDouble & " " & myNumb & cr after field "data"
end if
put longAdd(myDouble, myDouble) into myDouble
end repeat
end mouseup
Re: Routines for very large numbers.
hpsh.
I could not get your handler to work. For example, if I try to multiply 10 * 50, this is what appears in the field "data":
You do know that you do not need to declare any of the variables, right?
Anyway, I am sure that the problem is just what you say, an internal collision within LC (this was from Hypercard, you know. I just ported it over, basically unchanged, though HC had similar constraints). I tried to get around that by creating a series of sums, since the methodology of the "longAdd" routine has no length limit (I think).
So it is possible that I did not write "longMult" as well as I planned, and somewhere at the bottom of the list of arguments the procedure "crashes". I guess I will have to find out where that happens. Though I must say you sound like the perfect person to try your hand at that task as well.
Craig
I could not get your handler to work. For example, if I try to multiply 10 * 50, this is what appears in the field "data":
Code: Select all
1 10
2 40
4 80
8 160
16 320
32 640
Anyway, I am sure that the problem is just what you say, an internal collision within LC (this was from Hypercard, you know. I just ported it over, basically unchanged, though HC had similar constraints). I tried to get around that by creating a series of sums, since the methodology of the "longAdd" routine has no length limit (I think).
So it is possible that I did not write "longMult" as well as I planned, and somewhere at the bottom of the list of arguments the procedure "crashes". I guess I will have to find out where that happens. Though I must say you sound like the perfect person to try your hand at that task as well.
Craig
Re: Routines for very large numbers.
you got the series:
1 10
2 40
4 80
8 160
16 320
32 640
strange,yes has done something wrong then i tryed to clean up the code
it should have been
1 10
2 20
4 40
8 80
16 160
32 320
if my head is working ok this early in the morning
the next problem would be to find the line
32 320
16 160
2 20
and add togheter 320 + 160 + 20
oh think i see the error, try this
1 10
2 40
4 80
8 160
16 320
32 640
strange,yes has done something wrong then i tryed to clean up the code
it should have been
1 10
2 20
4 40
8 80
16 160
32 320
if my head is working ok this early in the morning
the next problem would be to find the line
32 320
16 160
2 20
and add togheter 320 + 160 + 20
oh think i see the error, try this
Code: Select all
on mouseUp
global myDouble
local myNumb
/*
need 3 field
field "data" is a scrollling field
field t1 and t2 is the factors to multiply
*/
put empty into field "data"
put 1 into myDouble
repeat until myDouble > field "t2"
if the number of lines of field "data" = 0 then
put field "t1" into myNumb
put myDouble & " " & myNumb & cr after field "data"
--put longAdd(myNumb,myNumb) into myNumb
else
put longAdd(myNumb,myNumb) into myNumb
put myDouble & " " & myNumb & cr after field "data"
end if
put longAdd(myDouble, myDouble) into myDouble
end repeat
end mouseup
Re: Routines for very large numbers.
ok, have worked with the code, but are getting the same problem with to large number
not sure what is wrong, maybe something happens then the numbers are being compared?
anyway if anyone want to check my code

anyway if anyone want to check my code
Code: Select all
on mouseUp
global myDouble
local myNumb, dSum, sSum,fSum,gSum
/*
need 5 field
field "data" is a scrollling field
field "data2" is a scrollling field
field t1 and t2 is the factors to multiply
field display is for the answer
*/
put empty into field "data"
put empty into dSum
put empty into sSum
put empty into fSum
put 1 into myDouble
put 0 into sSum
repeat until myDouble > field "t2"
if the number of lines of field "data" = 0 then
put field "t1" into myNumb
put myDouble & " " & myNumb & cr before field "data"
--put longAdd(myNumb,myNumb) into myNumb
else
put longAdd(myNumb,myNumb) into myNumb
put myDouble & " " & myNumb & cr before field "data"
end if
put longAdd(myDouble, myDouble) into myDouble
end repeat
put empty into field "data2"
repeat for each line tLine in field "data"
put word 1 of tLine into dSum
put longAdd(sSum,dSum) into gSum
if gSum <= field "t2" then
put gSum into sSum
put longAdd(fSum,word 2 of tLine) into fSum
put tLine & cr after field "data2"
end if
end repeat
put fSum into field "display"
end mouseup
Re: Routines for very large numbers.
This gives the wrong number:
Should be: 1234567890
Answer is: 1234567889.999999
The precision in Livecode appears to be weak. Not good when financial calculations are to be done.
I filed a bug report: http://quality.runrev.com/show_bug.cgi?id=15775
Code: Select all
on mouseUp
put 1234567890 into t1
put (t1^3)^(1/3)
end mouseUp
Answer is: 1234567889.999999
The precision in Livecode appears to be weak. Not good when financial calculations are to be done.
I filed a bug report: http://quality.runrev.com/show_bug.cgi?id=15775