Calculate With Decimal Numbers - Mikrotik Script

This is a script to do any math operation (+, -, *, and /) with decimal numbers and/or integers in RouterOS. Make sure to copy the text below EXACTLY and paste into a blank Mikrotik script's source. There are no command dependencies, just scripting syntax. To use it, it's simply a matter of setting the decimals and decimalop global variables from another script or the console. 3.x version --Doug 06:26, 27 July 2009 (EEST) Update: internally remove leading zeros when calculating # Performs operations on decimal numbers # This script can be run from command line or other script. # To run, set global variables then run this script # # Global variables (input): # decimalop = math operator ( +, -, *, or / ) # decimalplaces = decimal point places (0 = no decimal point) # decimals = string of decimal numbers seperated by spaces (non-negative (-)) # # Global variables (output): # decimalresult = result of calculation, "err" if error # # Example: # add 3 numbers (4.32, 28 and 0.12): # :global decimalop "+" # :global decimals "4.32 28 0.21" # /system script run # :put $decimalresut # ### Math Operations ### # Do not change this part :global decimals :global decimalop :global decimalplaces :global decimalresult "err" :local err 0 :local result "" :local divprecision "10" :local decimalsarray "" # Sanity checks :if ([:len $decimalplaces] = 0) do={:set decimalplaces 4} else={ :for cindex from=0 to=([:len $decimalplaces] - 1) do={ :local char [:pick $decimalplaces $cindex ($cindex + 1)] :if ($char != "0" && $char != "1" && $char != "2" && $char != "3" && $char != "4" && \ $char != "5" && $char != "6" && $char != "7" && $char != "8" && $char != "9") do={ :set err ($err + 1) } } } :if ($decimalop != "+" && $decimalop != "-" && $decimalop != "*" && $decimalop != "/") do={ :set err ($err + 1) } # Check decimals input and convert decimals to array for easier use :for d from=0 to=([:len $decimals] - 1) do={ :local char [:pick $decimals $d ($d + 1)] :if ($char = " ") do={ :set decimalsarray ($decimalsarray . ",") } else={ :if ($char = "." || $char = "0" || $char = "1" || $char = "2" || $char = "3" || $char = "4" || \ $char = "5" || $char = "6" || $char = "7" || $char = "8" || $char = "9" ) do={ :set decimalsarray ($decimalsarray . $char) } else={:set err ($err + 1)} } } :set decimalsarray [:toarray $decimalsarray] :foreach d in=$decimalsarray do={ :local dps 0 :for cindex from=0 to=([:len $d] - 1) do={ :if ([:pick $d $cindex ($cindex + 1)] = ".") do={:set dps ($dps + 1)} } :if ($dps > 1) do={:set err ($err + 1)} } # Only preform calculation if no error :if ($err = 0) do={ # Preform calculation from first to last number :local cloopindex 0 :local decimallen 0 :local curdeclen 0 :local tmpnum "" # get decimal length for use after calculation :foreach d in=$decimalsarray do={ :local decfound 0 :for cindex from=0 to=([:len $d] - 1) do={ :if ([:pick $d $cindex ($cindex + 1)] = ".") do={ :set curdeclen ([:len $d] - ($cindex + 1)) :if ($decimalop = "+") do={:if ($curdeclen > $decimallen) do={:set decimallen $curdeclen}} :if ($decimalop = "-") do={:if ($curdeclen > $decimallen) do={:set decimallen $curdeclen}} :if ($decimalop = "*") do={:set decimallen ($decimallen + $curdeclen)} :set decfound 1 } } :if ($decfound = 0) do={ :if ($decimalop = "+") do={:if ($decimallen < 1) do={:set decimallen 1}} :if ($decimalop = "-") do={:if ($decimallen < 1) do={:set decimallen 1}} :if ($decimalop = "*") do={:set decimallen ($decimallen + 1)} } } # Loop through decimals from start to finish :foreach d in=$decimalsarray do={ :local decfound 0 :for cindex from=0 to=([:len $d] - 1) do={ :if ([:pick $d $cindex ($cindex + 1)] = ".") do={ :set decfound 1 :set curdeclen [:len [:pick $d ($cindex + 1) [:len $d]]] :set tmpnum ([:pick $d 0 $cindex] . [:pick $d ($cindex + 1) [:len $d]]) } } :if ($decfound = 0) do={ :set curdeclen 1 :set tmpnum ($d . "0") } # Strip leading zeros :local zeroindex ([:len $tmpnum] - 1) :for cindex from=([:len $tmpnum] - 1) to=0 do={ :if ($cindex >= 0 && [:pick $tmpnum $cindex ($cindex + 1)] != "0") do={ :set zeroindex $cindex } } :set tmpnum [:pick $tmpnum $zeroindex [:len $tmpnum]] # Add and Subtract calculation :if ($decimalop = "+" || $decimalop = "-") do={ # add zeros to decimal :if ($curdeclen < $decimallen) do={ :for cindex from=$curdeclen to=($decimallen - 1) do={ :set tmpnum ($tmpnum . "0") } } :if ($decimalop = "+") do={ :if ($decimallen > 0) do={ :if ($cloopindex = 0) do={:set result $tmpnum} \ else={:set result ($result + $tmpnum) } } } :if ($decimalop = "-") do={ :if ($decimallen > 0) do={ :if ($cloopindex = 0) do={:set result $tmpnum} \ else={:set result ($result - $tmpnum) } } } # end add and subtract } # Multiply calculation :if ($decimalop = "*") do={ :if ($decimallen > 0) do={ :if ($cloopindex = 0) do={:set result $tmpnum} \ else={:set result ($result * $tmpnum)} } # end multiply } # Divide calculation :if ($decimalop = "/") do={ :if ($cloopindex = 0) do={:set result $d} else={ # calculate decimal point position and strip decimal point from result :local resultdecpos 0 :local resultlen 0 :local tmpresult "" # Strip out decimal point :for cindex from=0 to=([:len $result] - 1) do={ :if ([:pick $result $cindex ($cindex + 1)] = ".") do={ :set resultdecpos $cindex } else={:set tmpresult ($tmpresult . [:pick $result $cindex ($cindex + 1)])} } :set result $tmpresult :set resultlen [:len $result] :if ($curdeclen > ([:len $result] - $resultdecpos)) do={ :set resultdecpos 0 # add zeros to result :for r from=([:len $result] - $resultdecpos) to=$curdeclen do={ :set result ($result . "0") } } else={ :set resultdecpos ($resultdecpos + $curdeclen) } # Strip leading zeros :local zeroindex ([:len $result] - 1) :for cindex from=([:len $result] - 1) to=0 do={ :if ($cindex >= 0 && [:pick $result $cindex ($cindex + 1)] != "0") do={ :set zeroindex $cindex } } :set result [:pick $result $zeroindex [:len $result]] :local decimal "" :local dividend $result :local divisor $tmpnum :local quotient ($dividend / $divisor) :local remainder ($dividend - ($divisor * $quotient)) :if ($remainder > 0) do={ :local tmpremainder ($remainder . "0") :for x from=1 to=$divprecision do={ :local tmpdecimal ($tmpremainder / $divisor) :set decimal ($decimal . $tmpdecimal) :set tmpremainder (($tmpremainder - ($tmpdecimal * $divisor)) . "0") } } else={:set decimal "0"} :set result "" # shift decimal point left :if (($resultlen - $resultdecpos) > 0) do={ :if ([:len $quotient] < ($resultlen - $resultdecpos)) do={ :for cindex from=[:len $quotient] to=($resultlen - $resultdecpos - 1) do={ :set result ("0" . $result) } :set result ("0." . $result . $quotient) :set resultdecpos 1 } else={ :for cindex from=0 to=([:len $quotient]) do={ :if ($cindex = ([:len $quotient] - ($resultlen - $resultdecpos))) do={ :if ($cindex = 0) do={ :set result "0." :set resultdecpos 1 } else={ :set result ($result . ".") :set resultdecpos $cindex } } :set result ($result . [:pick $quotient $cindex ($cindex + 1)]) } } :set result ($result . $decimal) # :set resultdecpos [:len $result] } else={:set result ($quotient . "." . $decimal); :set resultdecpos [:len $quotient]} :set decimallen ([:len $result] - $resultdecpos - 1) # if end of array, strip decimal point :if ($cloopindex = ([:len $decimalsarray] - 1)) do={ :local tmpresult "" :for cindex from=0 to=([:len $result] - 1) do={ :if ([:pick $result $cindex ($cindex + 1)] != ".") do={ :set tmpresult ($tmpresult . [:pick $result $cindex ($cindex + 1)]) } } :set result $tmpresult } # end cloopindex } # end divide } :set cloopindex ($cloopindex + 1) # end d for } # Format result, insert decimal point :local newresult "" :if (([:len $result] - $decimallen) < 0) do={ :set newresult "0" :for r from=[:len $result] to=($decimallen - 1) do={ :set newresult ($newresult . "0") } :set result ($newresult . $result) } :set newresult "" :for r from=0 to=(([:len $result] - $decimallen - 1) + $decimalplaces) do={ :if ($r = ([:len $result] - $decimallen)) do={ :if ($r = 0) do={:set newresult ($newresult . "0.")} :if ($r > 0) do={ :if ([:pick $result ($r - 1) $r] = "-") do={:set newresult ($newresult . "0")} :set newresult ($newresult . ".") } } :if ($r >= [:len $result]) do={:set newresult ($newresult . "0")} else={ :set newresult ($newresult . [:pick $result $r ($r + 1)]) } } :if ([:len $newresult] > 0) do={:set result $newresult} #end err check } # If no errors occurred, set decimalresult to result of calculation :if ($err = 0) do={:set decimalresult $result} # ### End of Math Operations ###

Hits

<- Back To Home