; msgbox % SM_Solve("%sin(1.59)% e %log(1000)%") ;is equal to sin(1.59) e log(1000) = 999.816
; msgbox % SM_Solve("4 + ( 2*( 3+(4-2)*round(2.5) ) ) + (5c2)**(4c3)")
; msgbox % "The gravity on earth is: " SM_Solve("(6.67e-11 * 5.978e24) / 6.378e6^2")
; msgbox % Sm_fact(40) ;<--try puttin one more zero here
; msgbox,% SM_Mod( SM_Pow(3,77), 79)
; msgbox,% SM_Round("124389438943894389430909430438098232323.427239238023823923984",4)
; msgbox,% SM_ToExp("328923823982398239283923.238239238923", 3)
; msgbox,% SM_Divide("43.034934034904334", "89.3467436743", 10)
; msgbox,% SM_UniquePmt("abcdefghijklmnopqrstuvwxyz0123456789",12367679898956098)
; msgbox,% SM_Mod("-22","-7")
; msgbox % SM_fromexp("6.45423e10")
; msgbox,% SM_Divide("48.45","19.45",2)
; msgbox,% SM_UniquePmt("avi,annat,koiaur,aurkoi")
; msgbox,% SM_Solve("(28*45) - (45*28)")
; msgbox,% SM_Add("1280232382372012010120325634", "-12803491201290121201212.98")
; MsgBox,% SM_Solve("23898239238923.2382398923 + 2378237238.238239 - (989939.9939 * 892398293823)")
; msgbox,% SM_ToExp("0.1004354545")
; var = sqrt(10!) - ( 2**5 + 5*8 )
; msgbox,% SM_Solve(var)
;
; Msgbox,% SM_Greater(18.789, 187)
msgbox,% SM_Divide("434343455677690909087534208967834434444.5656", "8989998989898909090909009909090909090908656454520", 100)
MsgBox,% SM_Multiply("111111111111111111111111111111111111111111.111","55555555555555555555555555555555555555555555.555")
MsgBox,% SM_Prefect("00.002000")
; msgbox % t:=SM_Number2Base("10485761048", 2) ;base 2
; msgbox % f:=SM_Number2base("10485761048", 32) ;base 32
; msgbox % SM_Base2Number(t, 2) "`n" SM_Base2Number(f, 32)
return
; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=465
/*
Scientific MATHS LIBRARY ( Filename = Maths.ahk )
by Avi Aryan
v3.43
Thanks to hd0202, smorgasbord, Uberi and sinkfaze
Special thanks to smorgasbord for the factorial function
------------------------------------------------------------------------------
DOCUMENTATION - http://avi-aryan.github.io/ahk/functions/smaths.html
Math-Functions.ahk - https://github.com/avi-aryan/Avis-Autohotkey-Repo/blob/master/Functions/Math-Functions.ahk
##############################################################################
FUNCTIONS
##############################################################################
* NOTES ARE PROVIDED WITH EACH FUNCTION IN THE FORM OF COMMENTS. EXPLORE
* SM_Solve(Expression, AHK=false) --- Solves a Mathematical expression. (with extreme capabilites)
* SM_Add(number1, number2) --- +/- massive numbers . Supports Real Nos (Everything)
* SM_Multiply(number1, number2) --- multiply two massive numbers . Supports everything
* SM_Divide(Dividend, Divisor, length) --- Divide two massive numbers . Supports everything . length is number of decimals smartly rounded.
* SM_Greater(number1, number2, trueforequal=false) --- compare two massive numbers
* SM_Prefect(number) --- convert a number to most suitable form. like ( 002 to 2 ) and ( 000.5600 to 0.56 )
* SM_fact(number) --- factorial of a number . supports large numbers
* SM_toExp(number, decimals) --- Converts a number to Scientific notation format
* SM_FromExp(sci_num) --- Converts a scientific type formatted number to a real number
* SM_Pow(number, power) --- power of a number . supports large numbers and powers
* SM_Mod(Dividend, Divisor) --- Mod() . Supports large numbers
* SM_Round(number, decimals) --- Round() . Large numbers
* SM_Floor(number) --- Floor() . large numbers
* SM_Ceil(number) --- Ceil() . large number
* SM_e(N, auto=1) --- returns e to the power N . Recommend auto=1 for speed
* SM_Number2base(N, base) --- Converts N to base 'base'
* SM_Base2Number(H, base) --- Converts H in base 'base' to a real number
* SM_UniquePmt(pattern, ID, Delimiter=",") ;gives the unique permutation possible .
################################################################################
READ
################################################################################
* Pass the numbers as strings in each of these functions. This is done to avoid number trimming due to Internal AHK Limit
* For a collection of general Math functions, see < Math-functions.ahk >
*/
;msgbox % SM_Solve("%sin(1.59)% e %log(1000)%") ;is equal to sin(1.59) e log(1000) = 999.816
;msgbox % SM_Solve("4 + ( 2*( 3+(4-2)*round(2.5) ) ) + (5c2)**(4c3)")
;msgbox % "The gravity on earth is: " SM_Solve("(6.67e-11 * 5.978e24) / 6.378e6^2")
;msgbox % Sm_fact(40) ;<--try puttin one more zero here
;msgbox,% SM_Mod( SM_Pow(3,77), 79)
;msgbox,% SM_Round("124389438943894389430909430438098232323.427239238023823923984",4)
;msgbox,% SM_ToExp("328923823982398239283923.238239238923", 3)
;msgbox,% SM_Divide("43.034934034904334", "89.3467436743", 10)
;msgbox,% SM_UniquePmt("abcdefghijklmnopqrstuvwxyz0123456789",12367679898956098)
;msgbox,% SM_Mod("-22","-7")
;msgbox % SM_fromexp("6.45423e10")
;msgbox,% SM_Divide("48.45","19.45",2)
;msgbox,% SM_UniquePmt("avi,annat,koiaur,aurkoi")
;msgbox,% SM_Solve("(28*45) - (45*28)")
;msgbox,% SM_Add("1280232382372012010120325634", "-12803491201290121201212.98")
;MsgBox,% SM_Solve("23898239238923.2382398923 + 2378237238.238239 - (989939.9939 * 892398293823)")
;msgbox,% SM_ToExp("0.1004354545")
;var = sqrt(10!) - ( 2**5 + 5*8 )
;msgbox,% SM_Solve(var)
;Msgbox,% SM_Greater(18.789, 187)
;msgbox,% SM_Divide("434343455677690909087534208967834434444.5656", "8989998989898909090909009909090909090908656454520", 100)
;MsgBox,% SM_Multiply("111111111111111111111111111111111111111111.111","55555555555555555555555555555555555555555555.555")
;MsgBox,% SM_Prefect("00.002000")
;msgbox % t:=SM_Number2Base("10485761048", 2) ;base 2
;msgbox % f:=SM_Number2base("10485761048", 32) ;base 32
;msgbox % SM_Base2Number(t, 2) "`n" SM_Base2Number(f, 32)
;return
;###################################################################################################################################################################
;#Include, Maths.ahk
/*
SM_Solve(expression, ahk=false)
Solves the expression in string. SM_Solve() uses the powerful functions present in the library for processing
ahk = true will make SM_Solve() use Ahk's +-/* for processing. Will be faster
* You can use global variables in expressions . To make SM_Solve see them as global vars, surround them by %..%
* To nest expressions with brackets , you can use the obvious ( ) brackets
* You can use numbers in sci notation directly in this function . ("6.67e-11 * 4.23223e24")
* You can use ! to calulate factorial ( 48! ) ( log(1000)! )
* You can use ^ or ** to calculate power ( 2.2321^12 ) ( 4**14 )
* You can use p or c for permutation or combination
* Use %...% to use functions with e, c, p . ("4**sin(3.14) + 5c%log(100)% + %sin(1.59)%e%log(1000)% + log(1000)!")
Example
global someglobalvar := 26
msgbox,% SM_Solve("Sqrt(%someglobalvar%) * 4! * log(100) * ( 3.43e3 - 2^5 )")
*/
SM_Solve(expression, ahk=false){
static fchars := "e- e+ **- ** **+ ^- ^+ + - * / \" , rchars := "#< #> ^< ^> ^> ^< ^> ¢ ¤ ¥ ¦ ¦"
;Reject invalid
if expression=
return
;Check Expression for invalid
if expression is alpha
{
temp2 := %expression%
return %temp2% ;return value of expression if it is a global variable or nothing
}
else if expression is number
{
if !Instr(expression, "e")
return expression
}
;Fix Expression
StringReplace,expression,expression,%A_space%,,All
StringReplace,expression,expression,%A_tab%,,All
expression := SM_Fixexpression(expression)
; Solving Brackets first
while b_pos := RegexMatch(expression, "i)[\+\-\*\\\/\^]\(")
{
b_count := {"(": 1, ")": 0}
b_temp := Substr(expression, b_pos+2)
loop, parse, b_temp
{
b_count[A_LoopField] += 1
if b_count["("] = b_count[")"]
{
end_pos := A_index
break
}
}
expression := Substr(expression, 1, b_pos) SM_Solve( Substr(expression, b_pos+2, end_pos-1) ) Substr(expression, end_pos+b_pos+2)
}
;Changing +,-,e-,e+ and all signs to different things
expression := SM_FixExpression(expression) ;FIX again after solving brackets
loop,
{
if !(Instr(expression, "(")){
expression := SM_PowerReplace(expression, fchars, rchars, "All") ;power replaces replaces those characters
reserve .= expression
break
}
temp := Substr(expression, 1, Instr(expression, "(")) ;till 4+2 + sin(
temp := SM_PowerReplace(temp, fchars, rchars, "All") ;we dont want to replace +- inside functions
temp2 := SubStr(expression, Instr(expression, "(") + 1, Instr(expression, ")") - Instr(expression, "("))
reserve .= temp . temp2
expression := Substr(expression,Instr(expression, ")")+ 1)
}
;
expression := reserve
; The final solving will be done now
loop, parse, expression,¢¤¥¦
{
;Check for functions --
if RegExMatch(A_LoopField, "iU)^[a-z0-9_]+\(.*\)$") ;Ungreedy ensures throwing cases like sin(45)^sin(95)
{
fname := Substr(A_LoopField, 1, Instr(A_loopfield,"(") - 1) ;extract func
ffeed := Substr(A_loopfield, Instr(A_loopfield, "(") + 1, Instr(A_loopfield, ")") - Instr(A_loopfield, "(") - 1) ;extract func feed
loop, parse, ffeed,`,
{
StringReplace,feed,A_loopfield,",,All
feed%A_index% := SM_Solve(feed)
totalfeeds := A_index
}
if fname = SM_toExp
outExp := 1 ; now output will be in Exp , set feed1 as the number
, number := feed1
else if totalfeeds = 1
number := %fname%(feed1)
else if totalfeeds = 2
number := %fname%(feed1, feed2)
else if totalfeeds = 3
number := %fname%(feed1, feed2, feed3)
else if totalfeeds = 4
number := %fname%(feed1, feed2, feed3, feed4) ;Add more like this if needed
function := 1
}
else
number := A_LoopField , function := 0
;Perform the previous assignment routine
if (char != "") {
;The order is important here
if (!function) {
while match_pos := RegExMatch(number, "iU)%.*%", output_var)
output_var := Substr(output_var, 2 , -1)
, number := Substr(number, 1, match_pos-1) SM_Solve(Instr(output_var, "(") ? output_var : %output_var%) Substr(number, match_pos+Strlen(output_var)+2)
if Instr(number, "#") or Instr(number, "^")
number := SM_PowerReplace(number, "#< #> ^> ^<", "e- e ^ ^-", "All") ;replace #,^ back to e and ^
;Symbols
;As all use SM_Solve() , else-if is OK
if ( p := Instr(number, "c") ) or ( p := p + Instr(number, "p") ) ;permutation or combination
term_n := Substr(number, 1, p-1) , term_r := Substr(number,p+1)
, number := SM_Solve( term_n "!/" term_r "!" ( Instr(number, "c") ? "/(" term_n "-" term_r ")!" : "" ) )
else if Instr(number, "^")
number := SM_Pow( SM_Solve( SubStr(number, 1, posofpow := Instr(number, "^")-1 ) ) , SM_Solve( Substr(number, posofpow+2) ) )
else if Instr(number, "!")
number := SM_fact( SM_Solve( Substr(number, 1, -1) ) )
else if Instr(number, "e") ; solve e
number := SM_fromExp( number )
}
if (Ahk){
if char = ¢
solved := solved + (number)
else if char = ¤
solved := solved - (number)
else if char = ¦
{
if !number
return
solved := solved / (number)
}
else if char = ¥
solved := solved * (number)
}else{
if char = ¢
solved := SM_Add(solved, number)
else if char = ¤
solved := SM_Add(solved,"-" . number)
else if char = ¦
{
if !number
return
solved := SM_Divide(solved, number)
}
else if char = ¥
solved := SM_Multiply(solved, number)
}
}
if solved =
solved := number
char := Substr(expression, Strlen(A_loopfield) + 1,1)
expression := Substr(expression, Strlen(A_LoopField) + 2) ;Everything except number and char
}
return, outExp ? SM_ToExp( solved ) : SM_Prefect( solved )
}
;###############################################################################################################################
/*
SM_Add(number1, number2, prefect=true)
Adds or subtracts 2 numbers
To subtract A and B , do like SM_Add(A, "-" B) i.e. append a minus
*/
SM_Add(number1, number2, prefect=true){ ;Dont set Prefect false, Just forget about it.
;Processing
IfInString,number2,--
count := 2
else IfInString,number2,-
count := 1
else
count := 0
IfInString,number1,-
count+=1
;
n1 := number1
n2 := number2
StringReplace,number1,number1,-,,All
StringReplace,number2,number2,-,,All
;Decimals
dec1 := Instr(number1,".") ? StrLen(number1) - InStr(number1, ".") : 0
dec2 := Instr(number2,".") ? StrLen(number2) - InStr(number2, ".") : 0
if (dec1 > dec2){
dec := dec1
loop,% (dec1 - dec2)
number2 .= "0"
}
else if (dec2 > dec1){
dec := dec2
loop,% (dec2 - dec1)
number1 .= "0"
}
else
dec := dec1
StringReplace,number1,number1,.
StringReplace,number2,number2,.
;Processing
;Add zeros
if (Strlen(number1) >= StrLen(number2)){
loop,% (Strlen(number1) - strlen(number2))
number2 := "0" . number2
}
else
loop,% (Strlen(number2) - strlen(number1))
number1 := "0" . number1
n := strlen(number1)
;
if count not in 1,3 ;Add
{
loop,
{
digit := SubStr(number1,1 - A_Index, 1) + SubStr(number2, 1 - A_index, 1) + (carry ? 1 : 0)
if (A_index == n){
sum := digit . sum
break
}
if (digit > 9){
carry := true
digit := SubStr(digit, 0, 1)
}
else
carry := false
sum := digit . sum
}
;Giving sign
if (Instr(n2,"-") and Instr(n1, "-"))
sum := "-" . sum
}
;SUBTRACT ******************
elsE
{
;Compare numbers for suitable order
numbercompare := SM_Greater(number1, number2, true)
if !(numbercompare){
mid := number2
number2 := number1
number1 := mid
}
loop,
{
digit := SubStr(number1,1 - A_Index, 1) - SubStr(number2, 1 - A_index, 1) + (borrow ? -1 : 0)
if (A_index == n){
StringReplace,digit,digit,-
sum := digit . sum
break
}
if Instr(digit, "-")
borrow:= true , digit := 10 + digit ;4 - 6 , then 14 - 6 = 10 + (-2) = 8
else
borrow := false
sum := digit sum
}
;End of loop ;Giving Sign
;
If InStr(n2,"--"){
if (numbercompare)
sum := "-" . sum
}else If InStr(n2,"-"){
if !(numbercompare)
sum := "-" . sum
}else IfInString,n1,-
if (numbercompare)
sum := "-" . sum
}
;End of Subtract - Sum
;End
if ((sum == "-")) ;Ltrim(sum, "0") == ""
sum := 0
;Including Decimal
If (dec)
if (sum)
sum := SubStr(sum,1,StrLen(sum) - dec) . "." . SubStr(sum,1 - dec)
;Prefect
return, Prefect ? SM_Prefect(sum) : sum
}
;###################################################################################################################
/*
SM_Multiply(number1, number2)
Multiplies any two numbers
*/
SM_Multiply(number1, number2){
;Getting Sign
positive := true
if Instr(number2, "-")
positive := false
if Instr(number1, "-")
positive := !positive
number1 := Substr(number1, Instr(number1, "-") ? 2 : 1)
number2 := Substr(number2, Instr(number2, "-") ? 2 : 1)
; Removing Dot
dec := InStr(number1,".") ? StrLen(number1) - InStr(number1, ".") : 0
If n2dotpos := Instr(number2, ".")
dec := dec + StrLen(number2) - n2dotpos
StringReplace,number1,number1,.
StringReplace,number2,number2,.
; Multiplying
loop,% Strlen(number2)
number2temp .= Substr(number2, 1-A_Index, 1)
number2 := number2temp
;Reversing for suitable order
product := "0"
Loop,parse,number2
{
;Getting Individual letters
row := "0"
zeros := ""
if (A_loopfield)
loop,% (A_loopfield)
row := SM_Add(row, number1, 0)
else
loop,% (Strlen(number1) - 1) ;one zero is already 5 lines above
row .= "0"
loop,% (A_index - 1) ;add suitable zeroes to end
zeros .= "0"
row .= zeros
product := SM_Add(product, row, false)
}
;Give Dots
if (dec){
product := SubStr(product,1,StrLen(product) - dec) . "." . SubStr(product,1 - dec)
product := SM_Prefect(product)
}
;Give sign
if !(positive)
product := "-" . product
return, product
}
;######################################################################################################################################
/*
SM_Divide(number1, number2, length=10)
Divide any two numbers
length = defines the number of decimal places in the result
*/
SM_Divide(number1, number2, length=10){
;Getting Sign
positive := true
if (Instr(number2, "-"))
positive := false
if (Instr(number1, "-"))
positive := !positive
StringReplace,number1,number1,-
StringReplace,number2,number2,-
;Perfect them
number1 := SM_Prefect(number1) , number2 := SM_Prefect(number2)
;Cases
;if !number1 && !number2
; return 1
if !number2 ; return blank if denom is 0
return
;Remove Decimals
dec := 0
if Instr(number1, ".")
dec := - (Strlen(number1) - Instr(number1, ".")) ;-ve as when the num is multiplied by 10, 10 is divided
if Instr(number2, ".")
dec := Strlen(number2) - Instr(number2, ".") + dec + 0
StringReplace,number1,number1,.
StringReplace,number2,number2,.
number1 := Ltrim(number1, "0") , number2 := Ltrim(number2, "0")
decimal := dec , num1 := number1 , num2 := number2 ;These wiil be used to handle point insertion
n1 := Strlen(number1) , n2 := StrLen(number2) ;Stroring n1 & n2 as they will be used heavily below
;Widen number1
loop,% n2 + length
number1 .= "0"
coveredlength := 0 , dec := dec - n2 - length , takeone := false , n1f := n1 + n2 + length
;Start
while(number1 != "")
{
times := 0 , below := "" , lendivide := 0 , n1fromleft := (takeone) ? Substr(number1, 1, n2+1) : Substr(number1, 1, n2)
if SM_Greater(n1fromleft, number2, true)
{
todivide := n1fromleft
loop, 10
{
num2temp%A_index% := SM_Multiply(number2, A_index)
if !(SM_Greater(todivide, num2temp%A_index%, true)){
lendivide := (takeone) ? n2 + 1 : n2
times := A_index - 1 , below := num2temp%times%
break
}
}
res .= zeroes_r
}
else
{
todivide := SubStr(number1, 1, n2+1) ; :-P (takeone) will not be needed here
loop, 10
{
num2temp%A_index% := SM_Multiply(number2, A_index)
if !(SM_Greater(todivide, num2temp%A_index%, true)){
lendivide := n2 + 1
times := A_index - 1 , below := num2temp%times%
break
}
}
if (coveredlength != 0)
res .= zeroes_r "0"
}
res .= times , coveredlength+=(lendivide - Strlen(remainder)) ;length of previous remainder will add to number1 and so is not counted
remainder := SM_Add(todivide, "-" below)
if remainder = 0
remainder := ""
number1 := remainder . Substr(number1, lendivide + 1)
if SM_Greater("0", remainder, true)
{
zeroes_k := ""
loop,% Strlen(number1)
zeroes_k .= "0"
if (number1 == zeroes_k){
StringTrimRight,number1,number1,1
number1 := "1" . number1
res := SM_Multiply(res, number1)
break
}
}
if times = 0
break
zeroes_r := "" , takeone := false
if (remainder == "") {
loop,
if (Instr(number1, "0") == 1)
zeroes_r .= "0" , number1 := Substr(number1, 2) , coveredlength+=1
else
break
}
if (Strlen(remainder) == n2)
takeone := true
else
loop,% n2 - StrLen(remainder) - 1
zeroes_r .= "0"
}
;Putting Decimal points"
if (dec < 0)
{
oldformat := A_formatfloat
SetFormat,float,0.16e
Divi := Substr(num1,1,15) / Substr(num2,1,15) ; answer in decimals
decimal := decimal + Strlen(Substr(num1,16)) - Strlen(Substr(num2,16))
if (Instr(divi,"-"))
decimal := decimal - Substr(divi,-1) + 1
else
decimal := decimal + Substr(divi,-1) + 1
if (decimal > 0)
res := Substr(res, 1, decimal) . "." . Substr(res, decimal + 1)
else if (decimal < 0){
loop,% Abs(decimal)
zeroes_e .= "0"
res := "0." zeroes_e res
}
else
res := "0." res
SetFormat,float,%oldformat%
}
else
{
num := "1"
loop,% dec
num .= "0"
res := SM_Multiply(SM_Prefect(res), num)
}
return, ( (positive) ? "" : "-" ) . SM_Round(SM_Prefect(res), decimal < 0 ? Abs(decimal)+length : length)
}
;##########################################################################################################################################
/*
SM_UniquePmt(series, ID="", Delimiter=",")
Powerful Permutation explorer function that uses an unique algorithm made by the author to give a unique sequence linked to a number.
For example, the word "abc" has 6 permutations . So, SM_UniquePmt("abc", 1) gives a different sequence, ("abc", 2) a different till ("abc", 6)
As the function is powered by the the specialist Mod, Division and Multiply functions, it can handle series larger series too.
Examples --
msgbox,% SM_UniquePmt("abcd") ;leaving ID = "" gives all permutations
msgbox,% SM_UniquePmt("abcdefghijklmnopqrstuvwxyz123456789", 23322323323) ;<----- That's called huge numbers
*/
SM_UniquePmt(series, ID="", Delimiter=","){
if Instr(series, Delimiter)
loop, parse, series,%Delimiter%
item%A_index% := A_LoopField , last := lastbk := A_Index
else{
loop, parse, series
item%A_index% := A_loopfield
last := lastbk := Strlen(series) , Delimiter := ""
}
if (ID == "") ;Return all possible permutations
{
fact := SM_fact(last)
loop,% fact
toreturn .= SM_UniquePmt(series, A_index) . "`n"
return, Rtrim(toreturn, "`n")
}
posfactor := (SM_Mod(ID, last) == "0") ? last : SM_Mod(ID, last)
incfactor := (SM_Mod(ID, last) == "0") ? SM_Floor(SM_Divide(ID,last)) : SM_Floor(SM_Divide(ID,last)) + 1
loop,% last
{
tempmod := SM_Mod(posfactor + incfactor - 1, last) ;should be faster
posfactor := (tempmod == "0") ? last : tempmod ;Extraction point
res .= item%posfactor% . Delimiter , item%posfactor% := ""
loop,% lastbk
if (item%A_index% == "")
plus1 := A_index + 1 , item%A_index% := item%plus1% , item%plus1% := ""
last-=1
if (posfactor > last)
posfactor := 1
}
return, Rtrim(res, Delimiter)
}
;####################################################################################################################################
/*
SM_Greater(number1, number2, trueforqual=false)
Evaluates to true if number1 > number2
If the "trueforequal" param is true , the function will also evaluate to true if number1 = number2
*/
SM_Greater(number1, number2, trueforequal=false){
IfInString,number2,-
IfNotInString,number1,-
return, true
IfInString,number1,-
IfNotInString,number2,-
return, false
if (Instr(number1, "-") and Instr(number2, "-"))
bothminus := true
number1 := SM_Prefect(number1) , number2 := SM_Prefect(number2)
; Manage Decimals
dec1 := (Instr(number1,".")) ? ( StrLen(number1) - InStr(number1, ".") ) : (0)
dec2 := (Instr(number2,".")) ? ( StrLen(number2) - InStr(number2, ".") ) : (0)
if (dec1 > dec2)
loop,% (dec1 - dec2)
number2 .= "0"
else if (dec2 > dec1)
loop,% (dec2 - dec1)
number1 .= "0"
StringReplace,number1,number1,.
StringReplace,number2,number2,.
; Compare Lengths
if (Strlen(number1) > Strlen(number2))
return,% (bothminus) ? (false) : (true)
else if (Strlen(number2) > Strlen(number1))
return,% (bothminus) ? (true) : (false)
else ;The final way out
{
stop := StrLen(number1)
loop,
{
if (SubStr(number1,A_Index, 1) > Substr(number2,A_index, 1))
return bothminus ? 0 : 1
else if (Substr(number2,A_index, 1) > SubStr(number1,A_Index, 1))
return bothminus ? 1 : 0
if (a_index == stop)
return, (trueforequal) ? 1 : 0
}
}
}
;#########################################################################################################################################
/*
SM_Prefect(number)
Converts any number to Perfect form i.e removes extra zeroes and adds reqd. ones. eg > SM_Prefect(000343453.4354500000)
*/
SM_Prefect(number){
number .= "" ;convert to string if needed
number := RTrim(number, "+-")
if number=
return 0
if Instr(number, "-")
number := Substr(number, 2) , negative := true
if Instr(number, "."){
number := Trim(number, "0")
if (Substr(number,1,1) == ".") ;if num like .6767
number := "0" number
if (Substr(number, 0) == ".") ;like 456.
number := Substr(number, 1, -1)
return,% (negative) ? ("-" . number) : (number)
} ; Non-decimal below
else
{
if Trim(number, "0")
return negative ? ("-" . Ltrim(number, "0")) : (Ltrim(number, "0"))
else
return 0
}
}
;###########################################################################################################################################
/*
SM_Mod(dividend, divisor)
Gives remanider when dividend is divided by divisor
*/
SM_Mod(dividend, divisor){
;Signs
positive := true
if Instr(divisor, "-")
positive := false
if (Instr(dividend, "-"))
positive := !positive
dividend := Substr(dividend, Instr(dividend, "-") ? 2 : 1) , divisor := Substr(divisor, Instr(divisor, "-") ? 2 : 1) , Remainder := dividend
;Calculate no of occurances
if SM_Greater(dividend, divisor, true){
div := SM_Divide(dividend, divisor)
div := Instr(div, ".") ? SubStr(div, 1, Instr(div, ".") - 1) : 0
if ( div == "0" )
Remainder := 0
else
Remainder := SM_Add(dividend, "-" SM_Multiply(Divisor, div))
}
return, ( (Positive or Remainder=0) ? "" : "-" ) . Remainder
}
;############################################################################################################################################
/*
SM_ToExp(number, decimals="") // SM_Exp
Gives exponential form of representing a number.
If decimals param is omitted , it is automatically detected.
? SM_Exp was the function's name in old versions and so a dummy function has been created
*/
SM_Exp(number, decimals=""){
return SM_ToExp(number, decimals)
}
SM_ToExp(number, decimals=""){
if (dec_pos := Instr(number, "."))
{
number := SM_Prefect(number) , number := Substr(number, Instr(number, "0")=1 ? 2 : 1)
Loop, parse, number
{
if A_loopfield > 0
break
tempnum .= A_LoopField
}
number := Substr(number, Strlen(tempnum)+1) , power := dec_pos-Strlen(tempnum)-2
number2 := Substr(number, 2)
StringReplace,number2,number2,.
number := Substr(number, 1, 1) "." number2
decimals := ( decimals="" or decimals>Strlen(number2) ) ? Strlen(number2) : decimals
return SM_Round(number, decimals) "e" power
}
else
{
number := SM_Prefect(number) , decimals := ( decimals="" or decimals>Strlen(Substr(number,2)) ) ? Strlen(Substr(number,2)) : decimals
return SM_Round( Substr(number, 1, 1) "." Substr(number, 2), decimals ) "e" Strlen(number)-1
}
}
/*
SM_FromExp(expnum)
Converts exponential form to number
*/
SM_FromExp(expnum){
if !Instr(expnum, "e")
return expnum
n1 := Substr(expnum, 1, t := Instr(expnum, "e")-1) , n2 := Substr(expnum, t+2)
return SM_ShiftDecimal(n1, n2)
}
;#######################################################################################################################################
/*
SM_Round(number, decimals)
Rounds a infinitely sized number to given number of decimals
*/
SM_Round(number, decimals){
if Instr(number,".")
{
nofdecimals := StrLen(number) - ( Instr(number, ".") = 0 ? Strlen(number) : Instr(number, ".") )
if (nofdecimals > decimals)
{
secdigit := Substr(number, Instr(number,".")+decimals+1, 1)
if secdigit >= 5
loop,% decimals-1
zeroes .= "0"
number := SM_Add(Substr(number, 1, Instr(number, ".")+decimals), (secdigit >= 5) ? "0." zeroes "1" : "0")
}
else
{
loop,% decimals - nofdecimals
zeroes .= "0"
number .= zeroes
}
return, Rtrim(number, ".")
}
else
return, number
}
;###################################################################################################################################################
/*
SM_Floor(number)
Floor function with extended support. Refer to Ahk documentation for Floor()
*/
SM_Floor(number){
number := SM_Prefect(number)
if Instr(number, "-")
if Instr(number,".")
return, SM_Add(Substr(number, 1, Instr(number, ".") - 1), -1)
else
return, number
else
return, Instr(number, ".") ? Substr(number, 1, Instr(number, ".") - 1) : number
}
;##################################################################################################################################################
/*
SM_Ceil(number)
Ceil function with extended support. Refer to Ahk documentation for Ceil()
*/
SM_Ceil(number){
number := SM_Prefect(number)
if Instr(number, "-")
{
if Instr(number,".")
return, Substr(number, 1, Instr(number, ".") - 1)
else
return, number
}
else
return, Instr(number, ".") ? SM_Add( Substr(number, 1, Instr(number, ".") - 1), 1) : number
}
;#################################################################################################################################################
/*
SM_fact(number)
Gives factorial of number of any size. Try SM_fact(200) :-;
;--- Edit
Now SM_Fact() uses smorgasboard method for faster results
http://ahkscript.org/boards/viewtopic.php?f=22&t=176&p=4786#p4781
*/
SM_fact(N){
res := 1 , k := 1 , carry := 0
N -= 1
loop % N
{
StringSplit, l_times, res
index := l_times0
k := A_index + 1
Loop %index%
{
digit := k * l_times%index% + carry
if ( digit > 9 )
{
carry := RegExReplace(digit, "(.*)(\d)", "$1")
digit := RegExReplace(digit, "(.*)(\d)", "$2")
}
else
carry := 0
r := digit r
index --
}
if ( carry != 0 )
final := carry r
else
final := r
res := final
digit := index := final := r =
r := ""
carry := 0
}
return final ? final : 1
}
/*
SM_Pow(number, power)
Gives the power of a number . Uses SM_Multiply() for the purpose
*/
SM_Pow(number, power){
if (power < 1)
{
if !power ;0
return 1
if power Between -1 and 1
return number ** power
power := -power , I := Floor(power) , D := Mod(power, 1)
if Instr(number, "-") && D ;if number is - and power is - in decimals , it doesnt exist ... -4 ** -2.5
return
D_part := number ** D ;The power of decimal part
I_part := SM_Pow(number, I) ;Now I will always be >=1 . So it will fall in the below else part
return SM_Prefect( SM_Divide(1, SM_Multiply(I_part, D_part)) )
}
else
{
if power > 6
{
sqrt_c := Floor(Sqrt(power))
x_c := SM_Iterate(number, sqrt_c) , loopc := Floor(power/sqrt_c)
x_c_loop := SM_iterate(x_c, loopc) , remPow := power - (sqrt_c*loopc)
x_remPow := SM_iterate(number, remPow)
return SM_Multiply(x_c_loop, x_remPow)
}
else x_7_pow7 := 1
a := 1
loop % Mod(power, 7)
a := SM_Multiply(number, a)
return SM_Multiply(x_7_pow7, a)
}
}
/*
SM_e(N, auto=1)
Gives the power of e to N
auto = 1 enables smart rounding for faster results
Call auto as false (0) for totally accurate results. (may be slow)
*/
SM_e(N, auto=1){
static e := 2.71828182845905 , d := 14 ;rendering precise results with speed .
if (N > 5) and auto
e := SM_Round("2.71828182845905", (F := d-N+5)>2 ? F : 2)
return SM_Pow(e, N)
}
/*
SM_ base Conversion functions
via Base to Number and Number to Base conversion
Base = 16 for HexaDecimal , 2 for Binary, 8 for Octal and 10 for our own number system
*/
SM_Number2Base(N, base=16){
baseLen:=base<10 ? SM_Ceil((10/base)*Strlen(N)) : Strlen(N)
if SM_checkformat(N) && SM_Checkformat(base**(baseLen-1)) ;check if N and base**base (used below) is compatitible
loop % baseLen
D:=Floor(N/(T:=base**(baseLen-A_index))),H.=!D?0:(D>9?Chr(D+87):D),N:=N-D*T
else
loop % baseLen
D:=SM_Floor( SM_Divide(N , T:= SM_Pow(base, baselen-A_index)) ) , H.=!D?0:(D>9?Chr(D+87):D) , N:=SM_Add( N, "-" SM_Multiply(D,T) )
return Ltrim(H,"0")
}
SM_Base2Number(H, base=16){
StringLower, H, H ;convert to lowercase for Asc to work
S:=Strlen(H),N:=0
loop,parse,H
N := SM_Add( N, SM_Multiply( (A_LoopField*1="")?Asc(A_LoopField)-87:A_LoopField , SM_Pow(base, S-A_index) ) )
return N
}
;################# NON - MATH FUNCTIONS #######################################
;################# RESERVED ###################################################
; Checks if n is within AHK range
SM_Checkformat(n){
static ahk_ct := 9223372036854775807
if n < 0
return 0
if ( ahk_ct > n+0 )
return 1
}
;Shifts the decimal point
;specify -<dec_shift> to shift in left direction
SM_ShiftDecimal(number, dec_shift=0){
if Instr(number, "-")
number := Substr(number,2) , minus := 1
dec_pos := Instr(number, ".") , numlen := StrLen(number)
loop % Abs(dec_shift) ;create zeroes
zeroes .= "0"
if !dec_pos ;add decimal to integers
number .= ".0"
number := dec_shift>0 ? number zeroes : zeroes number ;append zeroes
dec_pos := Instr(number, ".") ;get dec_pos in the new number
StringReplace, number, number, % "."
number := Substr(number, 1, dec_pos+dec_shift-1) "." Substr(number, dec_pos+dec_shift)
return ( minus ? "-" : "" ) SM_Prefect(number)
}
; powers a number n times
SM_Iterate(number, times){
x := 1
loop % times
x := SM_Multiply(x, number)
return x
}
; fast string replace
SM_PowerReplace(input, find, replace, options="All"){
StringSplit, rep, replace, % A_space
loop, parse, find, % A_Space
StringReplace, input, input, % A_LoopField, % rep%A_index%, % options
return Input
}
SM_FixExpression(expression){
expression := Rtrim(expression, "+-=*/\^")
StringReplace,expression,expression,--,+,All
StringReplace,expression,expression,-+,-,All
StringReplace,expression,expression,+-,-,All
StringReplace,expression,expression,++,+,All
;Reject invalid
if expression=
return
;if (Substr(expression, 1, 1) != "+") or (Substr(expression, 1, 1) != "-")
if Substr(expression, 1, 1) == "-"
expression := "0" expression ;make it 0 - 10
else expression := "+" expression
loop,
{
if Instr(expression, "*-"){
fromleft := Substr(expression, 1, Instr(expression, "*-"))
StringGetPos,posplus,fromleft,+,R
StringGetPos,posminus,fromleft,-,R
if (posplus > posminus)
fromleft := Substr(fromleft, 1, posplus) "-" Substr(fromleft, posplus + 2)
else
fromleft := Substr(fromleft, 1, posminus) "+" Substr(fromleft, posminus + 2)
expression := fromleft . Substr(expression, Instr(expression, "*-") + 2)
}else if Instr(expression, "/-"){
fromleft := Substr(expression, 1, Instr(expression, "/-"))
StringGetPos,posplus,fromleft,+,R
StringGetPos,posminus,fromleft,-,R
if (posplus > posminus)
fromleft := Substr(fromleft, 1, posplus) "-" Substr(fromleft, posplus + 2)
else
fromleft := Substr(fromleft, 1, posminus) "+" Substr(fromleft, posminus + 2)
expression := fromleft . Substr(expression, Instr(expression, "/-") + 2)
}else if Instr(expression, "\-"){
fromleft := Substr(expression, 1, Instr(expression, "\-"))
StringGetPos,posplus,fromleft,+,R
StringGetPos,posminus,fromleft,-,R
if (posplus > posminus)
fromleft := Substr(fromleft, 1, posplus) "-" Substr(fromleft, posplus + 2)
else
fromleft := Substr(fromleft, 1, posminus) "+" Substr(fromleft, posminus + 2)
expression := fromleft . Substr(expression, Instr(expression, "\-") + 2)
}else if Instr(expression, "x-"){
fromleft := Substr(expression, 1, Instr(expression, "x-"))
StringGetPos,posplus,fromleft,+,R
StringGetPos,posminus,fromleft,-,R
if (posplus > posminus)
fromleft := Substr(fromleft, 1, posplus) "-" Substr(fromleft, posplus + 2)
else
fromleft := Substr(fromleft, 1, posminus) "+" Substr(fromleft, posminus + 2)
expression := fromleft . Substr(expression, Instr(expression, "x-") + 2)
}else
break
}
StringReplace,expression,expression,--,+,All
StringReplace,expression,expression,-+,-,All
StringReplace,expression,expression,+-,-,All
StringReplace,expression,expression,++,+,All
return, expression
}
;<------------------------------------------- BYE -------------------------------------------------------------------------------->
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。

评论(0)