I haven't tried anybody else's scripts here, but I would ask, what magnitude of number can your functions handle?
This question has prompted me to attempt some 'big int' functions that I had been meaning to write for a long time, i.e. functions than can handle numbers of infinite magnitude, by using string manipulation. Currently the functions can only handle positive integers, and can't handle subtraction or division, but all the difficult bits have been done. They have not been thoroughly tested.
I'm not sure what the best big int library is for AHK, but I know that this is good:
Scientific Maths - infinite precision Mathematics Library - Scripts and Functions - AutoHotkey Community
https://autohotkey.com/board/topic/9351 ... s-library/
Scientific Maths - Math Lib for Unlimited precision - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=465
@dmg: Hopefully everything is reasonably easy to follow here.
Functions so far:
JEE_BigIntAdd(oArray*) ;a sum function
JEE_BigIntMult(oArray*) ;a product function
JEE_BigIntPow(vNum, vPower)
JEE_BigIntCompare(vNum1, vNum2)
JEE_BigIntBaseToDec(vNumX, vBase, vList:="")
JEE_BigIntDecToBase(vNum, vBase, vList:="")
Btw re. base64, the encoding for storing file data, starts with ABC ... rather than 0123 ..., which is a little unusual if you're storing actual numbers.
Code: Select all
q:: ;test big int functions
;MsgBox, % JEE_BigIntAdd(1,2,3)
;MsgBox, % JEE_BigIntAdd(11,22,33)
;MsgBox, % JEE_BigIntMult(16,16)
;MsgBox, % JEE_BigIntMult(1,2,3,4)
;MsgBox, % JEE_BigIntMult(3,3,3,3)
;MsgBox, % JEE_BigIntPow(2,10)
;MsgBox, % JEE_BigIntPow(2,20)
;MsgBox, % JEE_BigIntPow(2,30)
;MsgBox, % JEE_BigIntPow(256,4)
;MsgBox, % JEE_BigIntPow(256,5)
;MsgBox, % JEE_BigIntPow(256,6)
;MsgBox, % JEE_BigIntPow(256,7)
;MsgBox, % JEE_BigIntPow(256,8)
;MsgBox, % JEE_BigIntCompare(11, 22)
;MsgBox, % JEE_BigIntCompare(110, 22)
;MsgBox, % JEE_BigIntCompare(110, 220)
;MsgBox, % JEE_BigIntCompare(11, "011")
;MsgBox, % JEE_BigIntCompare(11, "022")
;MsgBox, % JEE_BigIntBaseToDec("FF", 16)
;MsgBox, % JEE_BigIntBaseToDec("FFF", 16)
;MsgBox, % JEE_BigIntBaseToDec("FFFF", 16)
;MsgBox, % JEE_BigIntBaseToDec(10, 64)
;MsgBox, % JEE_BigIntBaseToDec(100, 64)
;MsgBox, % JEE_BigIntBaseToDec(1000, 64)
MsgBox, % JEE_BigIntDecToBase(0xFF+0, 16)
MsgBox, % JEE_BigIntDecToBase(0xABCDEF+0, 16)
MsgBox, % JEE_BigIntDecToBase(0xFEDCBA+0, 16)
MsgBox, % JEE_BigIntDecToBase(21, 2) ;10101
MsgBox, % JEE_BigIntDecToBase(64, 2) ;1000000
MsgBox, % JEE_BigIntDecToBase(65, 2) ;1000001
return
;==================================================
JEE_BigIntAdd(oArray*)
{
if !oArray.Length()
return 0
vSum := 0
vWidth := A_IsUnicode ? 2 : 1
Loop, % oArray.Length()
{
vLen1 := StrLen(vSum)
vLen2 := StrLen(oArray[A_Index])
vMax := vLen1 > vLen2 ? vLen1 : vLen2
vNum1 := Format("{:0" vMax "}", vSum)
vNum2 := Format("{:0" vMax "}", oArray[A_Index])
vCarry := 0
vSum := Format("{:0" (vMax+1) "}", 0)
Loop, % vMax
{
vChar1 := SubStr(vNum1, vMax+1-A_Index, 1)
vChar2 := SubStr(vNum2, vMax+1-A_Index, 1)
StrPut(Mod(vChar1+vChar2+vCarry,10), &vSum+(vMax+1-A_Index)*vWidth, 1)
vCarry := (vChar1+vChar2+vCarry >= 10)
}
if vCarry
StrPut(1, &vSum, 1)
vSum := LTrim(vSum, "0")
}
return vSum
}
;==================================================
JEE_BigIntMult(oArray*)
{
if !oArray.Length()
return
else if (oArray.Length() = 1)
return oArray.1
vSum := oArray.1
Loop, % oArray.Length() - 1
{
vNum := oArray[A_Index+1]
if (StrLen(vNum) > StrLen(vSum))
vTemp := vNum, vNum := vSum, vSum := vTemp
else
vTemp := vSum
vSum := 0
Loop, Parse, vNum
{
vChar := A_LoopField
oArray2 := {}
Loop, % vChar ;add original vSum to itself multiple times
oArray2.Push(vTemp)
vTemp2 := JEE_BigIntAdd(oArray2*) JEE_StrRept("0", StrLen(vNum)-A_Index)
vSum := JEE_BigIntAdd(vSum, vTemp2)
}
}
return LTrim(vSum, "0")
}
;==================================================
JEE_BigIntPow(vNum, vPower)
{
if (vPower = 0)
if (vNum = 0)
return
else
return 1
if (vPower = 1)
return vNum
oArray := {}
Loop, % vPower
oArray.Push(vNum)
return JEE_BigIntMult(oArray*)
}
;==================================================
;if vNum1 is bigger, return 1
;if vNum1 is smaller, return -1
;if vNum1 and vNum2 are equal, return 0
JEE_BigIntCompare(vNum1, vNum2)
{
if ("" vNum1 = vNum2)
return 0
vNum1 := LTrim(vNum1, "0")
vNum2 := LTrim(vNum2, "0")
if ("" vNum1 = vNum2)
return 0
if (StrLen(vNum1) > StrLen(vNum2))
return 1
else if (StrLen(vNum2) > StrLen(vNum1))
return -1
Loop, % StrLen(vNum1)
{
vChar1 := SubStr(vNum1,A_Index,1)
vChar2 := SubStr(vNum2,A_Index,1)
if (vChar1 > vChar2)
return 1
else if (vChar2 > vChar1)
return -1
;if (SubStr(vNum1,A_Index,1) > SubStr(vNum2,A_Index,1))
; return 1
;else if (SubStr(vNum2,A_Index,1) > SubStr(vNum2,A_Index,1))
; return -1
}
}
;==================================================
;vList := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;base64
JEE_BigIntBaseToDec(vNumX, vBase, vList:="")
{
static vList2, oArray
if (vList = "")
vList := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"
if !(vList = vList2)
{
oArray := {}
Loop, Parse, vList
oArray[Ord(A_LoopField)] := A_Index-1
vList2 := vList2
}
vSum := 0
vLen := StrLen(vNumX)
Loop, Parse, vNumX
{
vTemp := JEE_BigIntPow(vBase, vLen-A_Index)
vTemp := JEE_BigIntMult(vTemp, oArray[Ord(A_LoopField)])
vSum := JEE_BigIntAdd(vSum, vTemp)
}
return vSum
}
;==================================================
JEE_BigIntDecToBase(vNum, vBase, vList:="")
{
static vList2, oArray
if (vBase = 10)
return vNum
else if (vBase < 2)
return
if (vList = "")
vList := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"
if !(vList = vList2)
{
oArray := {}
Loop, Parse, vList
oArray[A_Index-1] := A_LoopField
vList2 := vList2
}
vNum := LTrim(vNum, "0")
if (StrLen(vNum) <= StrLen(vBase))
&& (vNum+0 < vBase)
return oArray[vNum]
vLen := StrLen(vNum)
if (vBase < 10)
Loop
{
vTemp := JEE_BigIntPow(vBase, vLen)
if (JEE_BigIntCompare(vTemp, vNum) = 1)
break
vLen++
}
vSum := 0
Loop, % vLen
{
vTemp := JEE_BigIntPow(vBase, vLen-A_Index)
vKeep := 0
Loop, % vBase - 1
{
vTemp2 := JEE_BigIntMult(vTemp, A_Index)
vTemp3 := JEE_BigIntAdd(vSum, vTemp2)
if (JEE_BigIntCompare(vTemp3, vNum) = 1)
break
vKeep := A_Index
vTemp4 := vTemp3
}
if vKeep
vSum := vTemp4
vNumX .= oArray[vKeep]
}
return LTrim(vNumX, "0")
}
;==================================================
JEE_StrRept(vText, vNum)
{
if (vNum <= 0)
return
return StrReplace(Format("{:" vNum "}","")," ",vText)
;return StrReplace(Format("{:0" vNum "}",0),0,vText)
}
Btw I would welcome any stand-alone functions specifically optimised for dec to/from base 64, that can/can't handle infinite magnitude. Also, dmg is right, the scripts posted so far, could be better explained, I would welcome any clarifications.
Some algorithm details: