Routines for very large numbers.

Got a LiveCode personal license? Are you a beginner, hobbyist or educator that's new to LiveCode? This forum is the place to go for help getting started. Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller

hpsh
Posts: 52
Joined: Tue Aug 25, 2015 8:06 pm

Re: Routines for very large numbers.

Post by hpsh » Wed Aug 26, 2015 8:41 am

don't really think its a bug, think the problem is then you do something like:

if myVala > myValb

it will work whit myVala and myValb as if it is int (think that is a 32 bit number?)

think that i will need to get my code to work is in best case make a function that compares 2 strings, and tells me what string are largest, or if they are equel.

but other people here has to be much better then me :-) have used some other languages, but i has never been any good in any of them.

MaxV
Posts: 1580
Joined: Tue May 28, 2013 2:20 pm
Contact:

Re: Routines for very large numbers.

Post by MaxV » Mon Aug 31, 2015 11:41 am

You have to write some routine to threat long numbers like strings and perform operations on strings.
Here you'll find an example with Rebol, no problem for any number as long as you like: http://rebol2.blogspot.it/2011/12/big-numbers.html
You can convert it to livecode.
Functions created are:
  • big-add
  • big-sub
  • big-multiply
  • big-divide
Rebo lenguage is simple, either it's the livecode if .

Code: Select all

>> big-add "123456789012345678901234567890" "123456789012345678901234567890"
== "246913578024691357802469135780"
>> big-sub "123456789012345678901234567890" "123456789012345678901234567890"
== "0"
>> big-multiply "123456789012345678901234567890" "123456789012345678901234567890"
== "15241578753238836750495351562536198787501905199875019052100"
>> big-divide "123456789012345678901234567890" "123456789012345678901234567890"
== ["1" "0"]
>> big-divide "123456789012345678901234567890" "1234567890123456789031234567"
== ["99" "1234567890123456787142345757"]
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10043
Joined: Sat Apr 08, 2006 7:05 am
Contact:

Re: Routines for very large numbers.

Post by FourthWorld » Mon Aug 31, 2015 4:46 pm

golive wrote:The precision in Livecode appears to be weak. Not good when financial calculations are to be done.
Only when working with values larger than are likely to appear in financial calculations.
The response there from team member Dr. Peter Brett may be useful for other readers here:
LiveCode uses 64-bit IEEE 754 floating-point representation for numbers. This provides around 16 digits of decimal precision, which should be enough for most users' financial calculations.

You are cubing a 10-digit number, which produces a 30-digit number. This is more than can be represented by a 64-bit floating point number.

The precision of the calculation in this example is exactly as defined by the LiveCode language specification and the IEEE 754 standard. I am therefore closing this report as "not a bug".
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10305
Joined: Wed May 06, 2009 2:28 pm

Re: Routines for very large numbers.

Post by dunbarx » Mon Aug 31, 2015 6:49 pm

For financial calculations, 16 digits is fine. That is about the number of pennies in the earth's GDP. For small nations like the United States, which accounts for less than a quarter of that value, well, we have not used half-cents in centuries.

But there are larger issues. For example, such precision would only give the diameter of the universe to a few million miles. Unacceptable when planning vacations to black holes.

Craig

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10305
Joined: Wed May 06, 2009 2:28 pm

longAdd and longMult

Post by dunbarx » Tue Sep 01, 2015 5:02 am

Here are two functions that will add or multiply two integers of any length. For multiplication:

Code: Select all

--Requires the "addZero" and "longAdd" functions below
function longMult arg1,arg2
   put the number of chars of arg1 into index1
   put the number of chars of arg2 into index2
   
   if index1 > 8 then
      repeat with y = index1 down to 1 step -8
         put space after char y of arg1
         if the length of word 1 of arg1 <= 8 then exit repeat
      end repeat
   end if
   
   if index2 > 8 then
      repeat with y = index2 down to 1 step -8
         put space after char y of arg2
         if the length of word 1 of arg2 <= 8 then exit repeat
      end repeat
   end if
   
   put the number of words of arg1 into arg1WordCount
   put the number of words of arg2 into arg2WordCount
   
      repeat with y = 1 to arg1WordCount
       repeat with u = 1 to arg2WordCount
         get ((arg1WordCount - y) * 8) + ((arg2WordCount - u) * 8) 
               put word y of arg1 *  word u of arg2 & addZero((it)) & return after temp
         end repeat
      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
   
     return the last line of temp
end longMult

function addZero var
   repeat var
      put 0 after zeros
   end repeat
   return zeros
end addZero
For addition:

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
This
Last edited by dunbarx on Tue Sep 01, 2015 1:49 pm, edited 1 time in total.

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10305
Joined: Wed May 06, 2009 2:28 pm

Re: Routines for very large numbers.

Post by dunbarx » Tue Sep 01, 2015 5:07 am

In a new thread ("longAdd and longMult") in the "Talking LiveCode" section, I posted two functions that will add or multiply two integers of any length.

Now the task of subtraction and division. Ugh.

Craig Newman

golive
Posts: 98
Joined: Wed Jul 01, 2015 5:16 am

Re: Routines for very large numbers.

Post by golive » Tue Sep 01, 2015 5:51 am

Interesting:

Code: Select all

on mouseUp
   put 1234567890.0987654321 into nNum
   answer "start:   "&nNum&cr&cr& \
         "     x1:  "&nNum*1 &cr& \
         "   x10:  "&nNum*10 &cr& \
         " x100:  "&nNum*100
         
end mouseUp
Gives:
1-09-2015 2-46-22 PM.png
1-09-2015 2-46-22 PM.png (4.52 KiB) Viewed 8120 times
I multiplied the starting number by 1, 10 and 100. Notice how the precision is less good when multiplied by 1 than when multiplied by 10.

golive
Posts: 98
Joined: Wed Jul 01, 2015 5:16 am

Re: longAdd and longMult

Post by golive » Tue Sep 01, 2015 6:17 am

Thanks for the routines.
Couldn't get long multiply to work.

This works:

Code: Select all

  put longMult(12345678,10) into tNum
But this doesn't:

Code: Select all

   put longMult(123456789,10) into tNum
(I'm still learning so don't know how to debug it).

istech
Posts: 211
Joined: Thu Sep 19, 2013 10:08 am

Re: Routines for very large numbers.

Post by istech » Tue Sep 01, 2015 7:54 am

dunbarx wrote:In a new thread ("longAdd and longMult") in the "Talking LiveCode" section, I posted two functions that will add or multiply two integers of any length.

Now the task of subtraction and division. Ugh.

Craig Newman
Hi there,

I have started a subtraction routine based on your add. But not sure I have taken the right route. As I have dealt with the carrys after the main loop. I will post the script when I think it's good enough. :wink:

Again thanks for your time everyone. Would be nice to have all the precision functions for all to use.

(@MaxV Rebol looks good. Just have not got the time to learn and convert the functions for LC)

MaxV
Posts: 1580
Joined: Tue May 28, 2013 2:20 pm
Contact:

Re: longAdd and longMult

Post by MaxV » Tue Sep 01, 2015 12:10 pm

You can try this functions, substract and divide will follow shortly:
########CODE#######
function bigAdd a1, a2
put reverse2(a1) into b1
put reverse2(a2) into b2
put 0 into mem
if length(b1) < length(b2) then
put b1 into temp
put b2 into b1
put temp into b1
end if
repeat while b2 is not empty
put (char 1 of b1) + (char 1 of b2) + mem into ppp
if length(ppp) = 1 then
put 0 into mem
put ppp before rrr
else
put 1 into mem
put char 2 of ppp before rrr
end if
delete char 1 of b1
delete char 1 of b2
end repeat
repeat while (b1 is not empty)
put mem + (char 1 of b1) into ppp
if length(ppp) = 1 then
put 0 into mem
put ppp before rrr
else
put 1 into mem
put char 2 of ppp before rrr
end if
delete char 1 of b1
end repeat
if mem = 1 then
put 1 before rrr
else
put b1 before rrr
end if
return rrr
end bigAdd

function reverse2 temp
repeat for each char tChar in temp
put tChar before temp2
end repeat
return temp2
end reverse2


function bigMultiply a1,a2
put reverse2(a1) into a1
put 0 into temp
repeat for each char tChar in a1
repeat with i=1 to tChar
put bigAdd(temp,a2) into temp
end repeat
put 0 after a2
end repeat
return temp
end bigMultiply

function bigGreater a1,a2
#compare two bignumbers:
#return true if n1 > n2
#return false if n1 < n2
#return empty if n1 = n2
if length(a1) is not length(a2) then
return ( length(a1) > length(a2) ) #this is evalueted true or false
else
if a1 = a2 then
return empty
else
repeat while ((char 1 of a1) = (char 1 of a2) )
delete char 1 of a1
delete char 1 of a2
end repeat
return ((char 1 of a1) > (char 1 of a2)) #this is evalueted true or false
end if
end if
end bigGreater
#####END OF CODE#####
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w

MaxV
Posts: 1580
Joined: Tue May 28, 2013 2:20 pm
Contact:

Re: longAdd and longMult

Post by MaxV » Tue Sep 01, 2015 1:24 pm

Ok, this contains all functions (bigAdd, bigSub, bigMultiply, BigDivide, bigGreater):

########CODE#######
function bigAdd a1, a2
put reverse2(a1) into b1
put reverse2(a2) into b2
put 0 into mem
if length(b1) < length(b2) then
put b1 into temp
put b2 into b1
put temp into b1
end if
repeat while b2 is not empty
put (char 1 of b1) + (char 1 of b2) + mem into ppp
if length(ppp) = 1 then
put 0 into mem
put ppp before rrr
else
put 1 into mem
put char 2 of ppp before rrr
end if
delete char 1 of b1
delete char 1 of b2
end repeat
repeat while (b1 is not empty)
put mem + (char 1 of b1) into ppp
if length(ppp) = 1 then
put 0 into mem
put ppp before rrr
else
put 1 into mem
put char 2 of ppp before rrr
end if
delete char 1 of b1
end repeat
if mem = 1 then
put 1 before rrr
else
put b1 before rrr
end if
return rrr
end bigAdd

function reverse2 temp
repeat for each char tChar in temp
put tChar before temp2
end repeat
return temp2
end reverse2


function bigMultiply a1,a2
put reverse2(a1) into a1
put 0 into temp
repeat for each char tChar in a1
repeat with i=1 to tChar
put bigAdd(temp,a2) into temp
end repeat
put 0 after a2
end repeat
return temp
end bigMultiply

function bigGreater a1,a2
#compare two bignumbers:
#return true if n1 > n2
#return false if n1 < n2
#return empty if n1 = n2
if length(a1) is not length(a2) then
return ( length(a1) > length(a2) ) #this is evalueted true or false
else
if a1 = a2 then
return empty
else
repeat while ((char 1 of a1) = (char 1 of a2) )
delete char 1 of a1
delete char 1 of a2
end repeat
return ((char 1 of a1) > (char 1 of a2)) #this is evalueted true or false
end if
end if
end bigGreater

function bigSub a1,a2
#substract the smallest big number from the largest one
if bigGreater(a2,a1) then
put a1 into temp
put a2 into a1
put temp into a2
end if
put reverse2(a1) into a1
put reverse2(a2) into a2
put 0 into mem
repeat while (a2 is not empty)
put (char 1 of a1) - mem + 10 - (char 1 of a2) into minus
if length(minus) = 1 then
put 1 into mem
put minus before rrr
else
put 0 into mem
put char 2 of minus before rrr
end if
delete char 1 of a1
delete char 1 of a2
end repeat
repeat while (a1 is not empty)
put char 1 of a1 + 10 - mem into minus
if length(minus) = 1 then
put 1 into mem
put minus before rrr
else
put 0 into mem
put char 2 of minus before rrr
end if
delete char 1 of a1
end repeat
#remove inital zeros
repeat while (char 1 of rrr is "0")
delete char 1 of rrr
end repeat
return rrr
end bigSub

function bigDivide a1,a2
#output is a block of two numbers "quotient , remainder"
if bigGreater(a2,a1) then
return ("0 , " & a1)
end if
if a1 = a2 then
return "1 , 0"
end if
put 0 into count
repeat while (bigGreater(a1,a2))
put bigSub(a1,a2) into a1
put bigAdd(1,count) into count
end repeat
if a1 = a2 then
put bigAdd(count,1) into count
put 0 into a1
end if
return (count & " , " & a1)
end bigDivide
#####END OF CODE#####
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w

istech
Posts: 211
Joined: Thu Sep 19, 2013 10:08 am

Re: Routines for very large numbers.

Post by istech » Tue Sep 01, 2015 1:48 pm

I'm going to move this conversation over to the below post.

http://forums.livecode.com/viewtopic.php?f=9&t=25211

MaxV has decided to save me some time and stress :wink: and has converted some Rebol functions. Special thanks for the time and effort to help me and the LC community to all involved.
Last edited by istech on Tue Sep 01, 2015 4:48 pm, edited 1 time in total.

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10305
Joined: Wed May 06, 2009 2:28 pm

Re: longAdd and longMult

Post by dunbarx » Tue Sep 01, 2015 1:53 pm

@goLive.
Couldn't get long multiply to work.
Both work for me.

Craig

istech
Posts: 211
Joined: Thu Sep 19, 2013 10:08 am

Re: longAdd and longMult

Post by istech » Tue Sep 01, 2015 2:31 pm

works for me:

Testing the BigSub:

123456789123456789123456789 - 1234567891023456789

expected: 123456787888888898100000000

LC native: 123456787888888900000000000

BigSub: 123456787888888898100000000

BigSub: Win

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10043
Joined: Sat Apr 08, 2006 7:05 am
Contact:

Re: Routines for very large numbers.

Post by FourthWorld » Tue Sep 01, 2015 4:34 pm

dunbarx, may I merge the newer thread here? It seems very on-topic, and would help newcomers find the complete conversation more easily.
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

Post Reply