Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

# BigInteger-Calculation with AHK

• Members
• 97 posts
• Last active: Jul 30 2005 12:17 AM
• Joined: 24 Apr 2005
I have written such a thing a few years ago with Delphi
and thought it might be funny to do it with AHK.
You can now add, subtract and multiply positive or negative
Integers with hunderts of digits

Here the code:
```#SingleInstance force
Gui, Add, Text, x10 y30 w51 h15, BigNum 1:
Gui, Add, Button, x65 y24 w25 h25 gPM1, +/-
Gui, Add, Edit, vLong1 r2 Number -WantReturn x96 y20 w350 h46,63562623
Gui, Add, Button, x96 y60 w55 h23, &Swap
Gui, Add, Button, x155 y60 w55 h23, &Compare
Gui, Add, Button, x214 y60 w55 h23, B1 + B2
Gui, Add, Button, x273 y60 w55 h23, B1 - B2
Gui, Add, Button, x332 y60 w55 h23, B1 * B2
Gui, Add, Button, x391 y60 w55 h23, B1 / B2
Gui, Add, Text, x10 y101 w51 h15, BigNum 2:
Gui, Add, Button, x65 y94 w25 h25 gPM2, +/-
Gui, Add, Edit, vLong2 r2 Number -WantReturn x96 y90 w350 h42,6355334
Gui, Add, Text, x96 y130 w350 h35,
(
Type in some large Integers (positive or negative) and test it
)
Gui, Add, Text, x10 y160 w51 h15, Result:
Gui, Show, x270 y110 h277 w477, BigInteger-Package by Rubberduck

Esc::exitApp
return

;**************************************************************************
;****** Internal Help-functions
;**************************************************************************
;//returns the maximum of x and y
Max(x,y)
{
IfLess x,%y%, Return y
Return x
}

;//simplyfies the use of Transform
Mod(In_Dividend,In_Divisor)
{
Transform, Ret_Val, Mod, %In_Dividend%, %In_Divisor%
return Ret_Val
}

;//simplyfies the use of Transform
Div(In_Dividend,In_Divisor)
{
Transform, Ret_Val, Floor, In_Dividend/In_Divisor
return, Ret_Val
}

;//Also usefull for any AHK-script. Swap the values of two variables
Swap_Values(Byref val1, ByRef Val2)
{
local dummy
dummy:=val1
val1:=val2
val2:=dummy
}

;//Is removing leading zeros from an LongInt String. If the String holds
;//an leading Minus it is kept -0000123 => -123 and 00985 => 985
{
local LCh, ZCh, WS
WS=%LongIntString%
StringLeft, LCh, WS, 1
if (LCh="-")
StringTrimLeft,WS,WS,1
loop
{
StringLeft, ZCh,WS,1
if (ZCh="0")
StringTrimLeft,WS,WS,1
else
break
}
If (WS="")   ;//If it is empty now make it 0
WS=0
if (LCh="-") ;//Add minus again if there was one
WS=-%WS%
LongIntString=%WS% ;//returns result BYREF !!!!
}

;//This function is comparing IntegerStrings (also WITH leading Minus)
;//Leading Zeros are removed by default to make comparison possible
;//If First  is smaller than Second -1 is returned
;//If First and Second are equal 0 is returned
;//If First is  bigger than Second  1 is returned
;//If one of the Strings is empty it is assumed to be 0
CompareLongIntStrings(ByRef FirstLongString,Byref SecondLongString,ShowMessage)
{
local FSize, FCh, SSize, SCh, Output, Ret_Val
StringLen, FSize, FirstLongString
StringLen, SSize, SecondLongString
StringLeft, FCh, FirstLongString, 1
StringLeft, SCh, SecondLongString, 1
if (FCh="-")and(SCh<>"-")
Ret_Val=-1
else
if (SCh="-")and(FCh<>"-")
Ret_Val=1
else
{
if (FSize>SSize)
{
if (FCh="-")and(SCh="-")
Ret_Val=-1
else
Ret_Val=1
}
else
if (SSize>FSize)
{
if (FCh="-")and(SCh="-")
Ret_Val=1
else
Ret_Val=-1
}
else
if (SSize=FSize)
{
Ret_Val=0 ;//assume we find no difference
loop, %SSize%
{
StringMid, Dig1, FirstLongString, %A_index%, 1
StringMid, Dig2, SecondLongString, %A_index%, 1
if (Dig1<>Dig2)  ;//Found a different digit
{
if (Dig1>Dig2)
{
If (FCh="-")and(SCh="-")
Ret_Val=-1
else
Ret_Val=1
break
}
else
if (Dig2>Dig1)
{
If (FCh="-")and(SCh="-")
Ret_Val=1
else
Ret_Val=-1
break
}
}
}
}
}
if (ShowMessage=1)
{
if (Ret_Val=-1)
OutPut=BigNum 1 is smaller than BigNum 2
else
if (Ret_Val=1)
OutPut=BigNum 1 is bigger than BigNum 2
else
OutPut=Both BigNum's are equal
GuiControl,, ResultEdit, %OutPut%
}
return, Ret_Val
}

;//Returns 1 if LongIntString has a leading Minus else returns 0
IsNeg(LongIntString)
{
local MCh
StringLeft, MCh,LongIntString,1
if (MCh="-")
return, 1
else
return, 0
}

;//Returns a LongIntString with removed Minus, what
;//simply means it returns an ABS'd LongIntString
ABSLongintString(LongIntString)
{
local MCh
StringLeft, MCh, LongIntString, 1
if (MCh="-")
{
StringTrimLeft,LongIntString,LongIntString,1
return %LongIntString%
}
else
return %LongIntString%
}

;//Is adding leading zeros to the strings so they have same length
MakeFitLength(ByRef FirstLongString,Byref SecondLongString)
{
local LS1Size, LS2Size, FCh, SCh, Maxi, L1Diff, L2Diff
StringLeft, FCh, FirstLongString, 1
StringLeft, SCh, SecondLongString, 1
;//remove minus first if there are one
if (FCh="-")
StringTrimLeft,FirstLongString,FirstLongString,1
if (SCh="-")
StringTrimLeft,SecondLongString,SecondLongString,1
StringLen, LS1Size, FirstLongString
StringLen, LS2Size, SecondLongString
Maxi:=Max(LS1Size,LS2Size)
L1Diff:=Maxi-LS1Size+3
L2Diff:=Maxi-LS2Size+3
loop, %L1Diff%
FirstLongString=0%FirstLongString%
loop, %L2Diff%
SecondLongString=0%SecondLongString%
;//Put back Minus if there was one
if (FCh="-")
FirstLongString=-%FirstLongString%
if (SCh="-")
SecondLongString=-%SecondLongString%
}

;//This function is subtracting Second from first and ALWAYS awaits
;//bigger than second so the result always will be positive e.g. 1000-456=544.
;//This function is only for internal use and called by the real ADD-SUB-Functions
ABSLongIntStringSub(FirstLongString,SecondLongString)
{
local MaxLength, ResultString, Erg, value1, value2, Sum, Rem
Rem = 0
ResultString =
StringLen, MaxLength, FirstLongString
loop, %MaxLength%
{
StringMid,value1,FirstLongString,MaxLength+1-A_index,1
StringMid,value2,SecondLongString,MaxLength+1-A_index,1
Sum:=value1-(value2+rem)
Rem:=Div((9-sum),10)
Erg:=Mod((sum+10),10)
ResultString=%Erg%%ResultString%
}
return, %Resultstring%
}

;//This is the REAL Function that is able to subtract one LongIntString
;//from another. Is subtracting Second from First (LongStrings) and returns the
;//Result as STRING. Now is supporting positive AND negative Long-Integers
LongIntStringSub(FirstLongString,SecondLongString)
{
local WS1, WS2, WSResult, FIsNeg, SIsNeg, ABSCompi
;//remember the minus
FIsNeg:=IsNeg(FirstLongString)
SIsNeg:=IsNeg(SecondLongString)
;//remove the minus on workstrings
WS1:=ABSLongIntString(FirstLongString)
WS2:=ABSLongIntString(SecondLongString)
;//compare absolute size of BigNums
ABSCompi:=CompareLongintStrings(WS1,WS2,0)
;//Make Strings same length with added zeroes
MakeFitLength(WS1,WS2)
If (FIsNeg="0" and SIsNeg="1") ;//First pos, second neg.  "x - -y" => "(x+y)"
else
If (FIsNeg="1" and SIsNeg="0") ;//First neg, sec pos. "-x - y" => "-(x+y)"
else
If (FIsNeg="1" and SIsNeg="1") ;//Both are negative
{
if (ABSCompi=0)  ;//Both are same ABS-size. E.G. -5 - -5 => Result 0
return, 0
else
if (ABSCompi=1)  ;//E.G. -1000 - -20 = -980 => Result negative
WSResult:=-ABSLongIntStringSub(WS1,WS2)
else
if (ABSCompi=-1) ;//E.G. -20 - -1000 = +980 => Result positive
WSResult:=ABSLongIntStringSub(WS2,WS1)
}
else
If (FIsNeg="0" and SIsNeg="0") ;//Both are positive
{
if (ABSCompi=0)  ;//Both are same ABS-size. E.G. 5 - 5 => Result 0
return, 0
else
if (ABSCompi=1)  ;//E.G. 1000 - 20 = 980 => Result positive
WSResult:=ABSLongIntStringSub(WS1,WS2)
else
if (ABSCompi=-1) ;//E.G. 20 - 1000 = -980 => Result negative
WSResult:=-ABSLongIntStringSub(WS2,WS1)
}
return, %WSResult%
}

;//This function is adding First and Second and always awaits Strings
;//(minuses removed) and prepared with MakeFitLength()
;//This function is only for internal use and called by the real ADD-SUB-Functions
{
local MaxLength, ResultString, Erg, value1, value2, sum, Rem
Rem = 0
ResultString =
StringLen, MaxLength, FirstLongString
loop, %MaxLength%
{
StringMid,value1,FirstLongString,MaxLength+1-A_index,1
StringMid,value2,SecondLongString,MaxLength+1-A_index,1
Sum:=Value1+Value2+rem
Erg:=Mod(Sum,10)
Rem:=Div(Sum,10)
ResultString=%Erg%%ResultString%
}
return, %Resultstring%
}

{
local WS1, WS2, WSResult, FIsNeg, SIsNeg, ABSCompi
;//remember the minus
FIsNeg:=IsNeg(FirstLongString)
SIsNeg:=IsNeg(SecondLongString)
;//remove the minus on workstrings
WS1:=ABSLongIntString(FirstLongString)
WS2:=ABSLongIntString(SecondLongString)
;//compare absolute size of BigNums
ABSCompi:=CompareLongintStrings(WS1,WS2,0)
;//Make Strings same length with added zeroes
MakeFitLength(WS1,WS2)
If (FIsNeg="0" and SIsNeg="0") ;//Both positive =>Result positive
else
If (FIsNeg="1" and SIsNeg="1") ;//Both negative =>Result negative
else
If (FIsNeg="1" and SIsNeg="0") ;//First negative, Second positive, further checking
{
if (ABSCompi=0)  ;//Both are same ABS-size. E.G. -5 + 5 => Result 0
return, 0
else
if (ABSCompi=1)  ;//E.G. -1000 + 20 = -980 => Result negative
WSResult:=-ABSLongIntStringSub(WS1,WS2)
else
if (ABSCompi=-1) ;//-20 + 1000 = +980 => Result positive
WSResult:=ABSLongIntStringSub(WS2,WS1)
}
else
If (FIsNeg="0" and SIsNeg="1") ;//First positive, Second negative, further checking
{
if (ABSCompi=0)  ;//Both are same ABS-size. E.G. 5 + -5 => Result 0
return, 0
else
if (ABSCompi=1)  ;//E.G. 1000 + -20 = +980 => Result positive
WSResult:=ABSLongIntStringSub(WS1,WS2)
if (ABSCompi=-1) ;//E.G. 20 + -1000 = -980 => Result negative
WSResult:=-ABSLongIntStringSub(WS2,WS1)
}
return, %WSResult%
}

StringGetChar(In_String,In_Posi,Param3)
{
local Length, Ret_Val
Ret_Val =
StringLen, Length, In_String
if (In_Posi>Length)or(length=0)or(In_Posi<1)
return Ret_Val
If (Param3=R)
StringMid,Ret_Val,In_String,Length+1-In_Posi,1
else
StringMid,Ret_Val,In_String,In_Posi,1
return, %Ret_Val%
}

;//Is multiplying FirstLongString and SecondLongString
LongIntStringMult(FirstLongString,SecondLongString)
{
local ResultString, MulRes, RightVal, LeftVal, Loop1Count, OutLoopCounter
local Loop2Count, InLoopCounter, ABSCompi, Help, ZeroAdd, FIsNeg, SIsNeg
;//remember the minus
FIsNeg:=IsNeg(FirstLongString)
SIsNeg:=IsNeg(SecondLongString)
;//remove the minus on workstrings
WS1:=ABSLongIntString(FirstLongString)
WS2:=ABSLongIntString(SecondLongString)
;//compare absolute size of BigNums
ABSCompi:=CompareLongintStrings(WS1,WS2,0)
if (ABSCompi=1)   ;//We do BiggerNum * SmallerNum
Swap_Values(WS1,WS2)
StringLen, Loop1Count, WS1
StringLen, Loop2Count, WS2
OutLoopCounter=0
loop, %Loop1Count%
{
OutLoopCounter+=1
Help =
Rem = 0
InLoopCounter=0
loop, %loop2Count%
{
InLoopCounter+=1
RightVal:=StringGetChar(WS2,InLoopCounter,R)
LeftVal:=StringGetChar(WS1,OutLoopCounter,R)
MulRes:=(LeftVal*RightVal)+rem
rem:=Div(Mulres,10)
Rest:=Mod(Mulres,10)
Help=%Rest%%Help%
}
Help=%rem%%Help%  ;/Not sure if thies right ???
Help=%Help%0
MakeFitLength(ResultString,Help)
}
If ((FIsNeg="1") and (SIsNeg="0")) or ((FIsNeg="0") and (SIsNeg="1"))
return, -%Resultstring%
else
return, %Resultstring%
}

ButtonCompare:
Gui, Submit, NoHide
CompareLongIntStrings(Long1,Long2,1)
;//Both are written back without leading zeros
GuiControl,,Long1,%Long1%
GuiControl,,Long2,%Long2%
return

ButtonSwap:
Gui, Submit, NoHide
Swap_Values(Long1,Long2)
GuiControl,,Long1,%Long1%
GuiControl,,Long2,%Long2%
return

PM1:
Gui, Submit, NoHide
if (IsNeg(Long1)="1")
{
Long1:=ABSLongintString(Long1)
GuiControl,,Long1,%Long1%
}
else
GuiControl,,Long1,-%Long1%
return

PM2:
Gui, Submit, NoHide
if (IsNeg(Long2)="1")
{
Long2:=ABSLongintString(Long2)
GuiControl,,Long2,%Long2%
}
else
GuiControl,,Long2,-%Long2%
return

ButtonB1+B2:
Gui, Submit, NoHide
GuiControl,, ResultEdit, %Summy%`n`nHopefully the result is OK :)
return

ButtonB1-B2:
Gui, Submit, NoHide
Summy:=LongIntStringSub(Long1,Long2)
GuiControl,, ResultEdit, %Summy%`n`nHopefully the result is OK :)
return

ButtonB1*B2:
Gui, Submit, NoHide
Summy:=LongIntStringMult(Long1,Long2)
GuiControl,, ResultEdit, %Summy%`n`nHopefully the result is OK :)
return

ButtonB1/B2:
MsgBox, Are you crazy ?`nThe Result mostly will be a float`n`nOk, I will work on this later :)
return
```

Greetings From Rubberduck
Wer keine Antworten hat muss nicht dumm sein,
dumm ist nur der welcher keine Fragen hat.

• Members
• 97 posts
• Last active: Jul 30 2005 12:17 AM
• Joined: 24 Apr 2005
I changed the code. Now all calculation is done only with Strings.

This means you can add, subtract or multiply two string in the form:

-923892368893478973489349857938475983475893457..............or
1872364782634908092348902348092384092834094233..............

I thought this would be useful ti handle really larger integers.

If there is interest, I try to modify it for Floats and add also divison.
There is no guarantie that calculation is done properly, but I think it
is calculating right. If you find bugs post it.
Wer keine Antworten hat muss nicht dumm sein,
dumm ist nur der welcher keine Fragen hat.