Page 4 of 5
Re: Routines for very large numbers.
Posted: Mon Sep 07, 2015 3:31 am
by golive
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.
Re: Routines for very large numbers.
Posted: Tue Sep 08, 2015 1:59 pm
by MaxV
I think it's a time problem, every size differences between the two numbers increase the time exponentially.
Re: Routines for very large numbers.
Posted: Tue Sep 08, 2015 2:33 pm
by MaxV
Now I can confirm it,
the request
Results:
9999999 , 9
Waiting just 45 minutes...

Re: Routines for very large numbers.
Posted: Wed Sep 09, 2015 9:31 am
by golive
25 minutes here
(Windows 8.1)
So not really usable, unfortunately.
Re: Routines for very large numbers.
Posted: Wed Sep 09, 2015 10:35 am
by MaxV
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.
Re: Routines for very large numbers.
Posted: Wed Sep 09, 2015 11:11 am
by istech
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?
Re: Routines for very large numbers.
Posted: Wed Sep 09, 2015 1:49 pm
by MaxV
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
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.
Re: Routines for very large numbers.
Posted: Thu Sep 10, 2015 2:54 am
by golive
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:
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
Re: Routines for very large numbers.
Posted: Thu Sep 10, 2015 10:19 am
by MaxV
The first case is correct, but you read the result wrongly
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.
Re: Routines for very large numbers.
Posted: Thu Sep 10, 2015 10:31 am
by MaxV
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.
Re: Routines for very large numbers.
Posted: Fri Sep 11, 2015 5:49 am
by golive
@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?
Re: Routines for very large numbers.
Posted: Mon Sep 14, 2015 11:25 am
by MaxV
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.
Re: Routines for very large numbers.
Posted: Tue Sep 15, 2015 12:42 am
by golive
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?
Re: Routines for very large numbers.
Posted: Tue Sep 15, 2015 5:35 am
by dunbarx
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
Re: Routines for very large numbers.
Posted: Tue Sep 15, 2015 8:44 am
by MaxV
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