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

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

Re: Routines for very large numbers.

Post by golive » Mon Sep 07, 2015 3:31 am

istech wrote:I have been testing the routines over the last couple days and all but one appear to work as expected. The function in question is "BigDivide"

Can someone confirm that if you do.

put bigDivide(99999999,10) into t
answer t

LC stops responding or crashes. This does not happen on every calculation only on some trying to narrow it down.
Yes, you are right.
MaxV's bigDivide hangs my PC as well.

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

Re: Routines for very large numbers.

Post by MaxV » Tue Sep 08, 2015 1:59 pm

I think it's a time problem, every size differences between the two numbers increase the time exponentially.
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: Routines for very large numbers.

Post by MaxV » Tue Sep 08, 2015 2:33 pm

Now I can confirm it,
the request

Code: Select all

put bigDivide(99999999,10)
Results:
9999999 , 9
Waiting just 45 minutes... :lol:
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w

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

Re: Routines for very large numbers.

Post by golive » Wed Sep 09, 2015 9:31 am

25 minutes here
(Windows 8.1)

So not really usable, unfortunately.

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

Re: Routines for very large numbers.

Post by MaxV » Wed Sep 09, 2015 10:35 am

Well, the bigDivide() function has to be improved for efficiency.
If you have any idea, please post your code here.
I'll work on it.
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 » Wed Sep 09, 2015 11:11 am

Code: Select all

breakpoint 
repeat while (bigGreater(a1,a2))
      put bigSub(a1,a2) into a1
      put bigAdd(1,count) into count
      wait 0 milliseconds with messages
   end repeat
Thanks MaxV. Addling the with 0 milliseconds stops the GUI freeze up. But the time taken to process the sum is not efficient as MaxV said. Maybe some chunking of the numbers may speed it up?

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

Re: Routines for very large numbers.

Post by MaxV » Wed Sep 09, 2015 1:49 pm

Solved, I just divided the big number in smallest pieces. Please add and subistute these functions (bigDivide and bigDivide2):

Code: Select all

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 & comma & a1)
end bigDivide

function bigDivide2 a1,a2     
   put length(a1) into ldividendo
   put length(a2) into ldivisore   
   if ldividendo <= ldivisore then 
      return bigDivide(a1,a2)
   end if   
   put char 1 to ldivisore of a1 into tDiv
   put bigDivide(tDiv,a2) into rrr 
   put item 1 of rrr into quoziente
   put item 1 of rrr into resto
   put ldivisore + 1 into nn   
   repeat with i = nn  to ldividendo
      put char i of a1 after resto
      put bigDivide(resto,a2) into temp
      put item 1 of temp after quoziente
      put item 2 of temp into resto
   end repeat
   return (quoziente & comma & resto)
end bigDivide2
so

Code: Select all

put bigDivide2(999999999,10)
returns
99999999,9
in less than a second.
Please test bigDivide2 and let me know.

TO DO:
working with negative numbers. At the present the substract function generates only positive numbers (like an abs function). Moreover all other functions work only with positive numbers.
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w

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

Re: Routines for very large numbers.

Post by golive » Thu Sep 10, 2015 2:54 am

MaxV wrote:Solved, I just divided the big number in smallest pieces. Please add and subistute these functions (bigDivide and bigDivide2):
Hi MaxV

Well done on the speed; now very fast.

But accuracy of result is not so good.

Example:

Code: Select all

put bigDivide2(123,111) into tNum
Calculator gives: 1.108108108108108
bigDivide2 gives: 1.12



Another example:

Code: Select all

put bigDivide2(123456789,12345678) into tNum
Calculator gives: 10.00000072900006
bigDivide2 gives: 10.19

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

Re: Routines for very large numbers.

Post by MaxV » Thu Sep 10, 2015 10:19 am

The first case is correct, but you read the result wrongly :lol:

bigDivide2(123,111) = 1,12 means 1 with remainder of 12 ( 111 * 1 + 12 = 123)

In other cases there is a bug, because it adds a "1" at the beginning of the remainder:

bigDivide2(123456789,12345678) = 10,19 means 10 with the remainder of 19

but the correct results is "10,9" , i.e. 10 with the remainder of 19; because ((10 * 12345678) + 9) = 123456789

I have to investigate further this bug in bigDivide2.
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: Routines for very large numbers.

Post by MaxV » Thu Sep 10, 2015 10:31 am

Ok, I found the bug, now this should work:

########CODE#######
function bigAdd a1, a2
#let's check if it's negative...
#end check
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
#let's check is a number is negative
if ((char 1 of a1 = "-") or (char 1 of a2 = "-")) then
if ((char 1 of a1 = "-") and (char 1 of a2 is not "-")) then
return false
end if
if ((char 1 of a1 is not "-") and ( char 1 of a2 = "-" )) then
return true
end if
#if we are here, both are negative
delete char 1 of a1
delete char 1 of a2
if a1 = a2 then
return empty
else
return (not bigGreater(a1,a2))
end if
end if
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 & comma & a1)
end bigDivide

function bigDivide2 a1,a2
put length(a1) into ldividendo
put length(a2) into ldivisore
if ldividendo <= ldivisore then
return bigDivide(a1,a2)
end if
put char 1 to ldivisore of a1 into tDiv
put bigDivide(tDiv,a2) into rrr
put item 1 of rrr into quoziente
put item 2 of rrr into resto
put ldivisore + 1 into nn
repeat with i = nn to ldividendo
put char i of a1 after resto
put bigDivide(resto,a2) into temp
put item 1 of temp after quoziente
put item 2 of temp into resto
end repeat
put removezeros(quoziente) into quoziente
put removezeros(resto) into resto
return (quoziente & comma & resto)
end bigDivide2

function removezeros temp
repeat while char 1 of temp is "0"
delete char 1 of temp
end repeat
return temp
end removezeros
#####END OF CODE#####

Please let me know.
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w

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

Re: Routines for very large numbers.

Post by golive » Fri Sep 11, 2015 5:49 am

@maxV Yes works fine, very nice! Thanks.

To display the result as a decimal number, I assume I can do something like this:

Code: Select all

on mouseUp
   put 123 into tNumerator
   put 118 into tDenominator
   put bigDivide2(tNumerator,tDenominator) into tNum
   answer tNum&cr&\
   item 1 of tNum &(item 2  of tNum)/tDenominator
end mouseUp
Actually this adds an extra zero ie item 1 of tNum &(item 2 of tNum)/tDenominator begins with "0."
Can you tell me what is the Livecode command to remove the leading zero?

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

Re: Routines for very large numbers.

Post by MaxV » Mon Sep 14, 2015 11:25 am

golive wrote:@maxV Yes works fine, very nice! Thanks.

To display the result as a decimal number, I assume I can do something like this:

Code: Select all

on mouseUp
   put 123 into tNumerator
   put 118 into tDenominator
   put bigDivide2(tNumerator,tDenominator) into tNum
   answer tNum&cr&\
   item 1 of tNum &(item 2  of tNum)/tDenominator
end mouseUp
Actually this adds an extra zero ie item 1 of tNum &(item 2 of tNum)/tDenominator begins with "0."
Can you tell me what is the Livecode command to remove the leading zero?
The function to remove leading zeros is removezeros(), however I'll avoid try to get decimal numbers that way, it isn't correct.
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w

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

Re: Routines for very large numbers.

Post by golive » Tue Sep 15, 2015 12:42 am

MaxV wrote: The function to remove leading zeros is removezeros(), however I'll avoid try to get decimal numbers that way, it isn't correct.

removezeros() is not in the dictionary. How do you use it?

Tried this (doesn't work):

Code: Select all

put  0.123456789 into t2
put removezeros(t2)
Also you say "I'll avoid try to get decimal numbers that way, it isn't correct." Why is it not correct?
How would you get the result as a decimal number?

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 15, 2015 5:35 am

GoLive.

The function "removeZeros" is part of MaxV's suite of handlers. It is not a native function. Look back at his post where he lists all his functions.

Craig

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

Re: Routines for very large numbers.

Post by MaxV » Tue Sep 15, 2015 8:44 am

golive wrote:
MaxV wrote: The function to remove leading zeros is removezeros(), however I'll avoid try to get decimal numbers that way, it isn't correct.
Also you say "I'll avoid try to get decimal numbers that way, it isn't correct." Why is it not correct?
How would you get the result as a decimal number?
For example:

1 / 3 = 0.3 is not correct, it's an approximation 0.3=3/10
1 / 3 = 0.33 is not correct, it's an approximation 0.33=33/100
1 / 3 = 0.333 is not correct, it's an approximation 0.333=333/1000
1 / 3 = 0.333333333 is not correct, it's an approximation
1 / 3 = 0.3333333333333333333333333333 is not correct, it's an approximation
1 / 3 = 0.3333333333333333333333333333333333 is not correct, it's an approximation
1 / 3 = 0.3333333333333333333333333333333333333333333333333333333333 is not correct, it's an approximation
1 / 3 = 0 with remainder of 1. This is the only correct solution contemplating all digits
Livecode Wiki: http://livecode.wikia.com
My blog: https://livecode-blogger.blogspot.com
To post code use this: http://tinyurl.com/ogp6d5w

Post Reply