Advertisement
Guest User

str_math.bash bv1.2

a guest
May 23rd, 2016
310
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 19.19 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3.  
  4.  
  5.  
  6. ## Script originally converted from batch script
  7. ## There is no warranty on this script or it's results
  8. ## Provided as-is bv1.2
  9.  
  10.  
  11.  
  12. ################################################################################
  13. ################################### Functions ##################################
  14. ################################################################################
  15.  
  16.  
  17. function isgreater
  18. {
  19.     local _GTR_NUM=($1 $2)
  20.     for i in 0 1; do
  21.         while [[ "${_GTR_NUM[$i]:0:1}" == "0" ]]; do
  22.             _GTR_NUM[$i]=${_GTR_NUM[$i]:1}
  23.         done
  24.         if [[ -z "${_GTR_NUM[$i]}" ]]; then
  25.             _GTR_NUM[$i]=0
  26.         fi
  27.     done
  28.     if [[ ${#_GTR_NUM[0]} -gt ${#_GTR_NUM[1]} ]]; then
  29.         return 1
  30.     elif [[ ${#_GTR_NUM[1]} -gt ${#_GTR_NUM[0]} ]]; then
  31.         return 3
  32.     else
  33.         for ((j=0; j<${#_GTR_NUM[0]}; j++)); do
  34.             if [[ ${_GTR_NUM[0]:j:1} -gt ${_GTR_NUM[1]:j:1} ]]; then
  35.                 return 1
  36.             fi
  37.             if [[ ${_GTR_NUM[1]:j:1} -gt ${_GTR_NUM[0]:j:1} ]]; then
  38.                 return 3
  39.             fi
  40.         done
  41.     fi
  42.     return 2
  43. }
  44.  
  45. function str_add
  46. {
  47.     local _ADD_NUM=($1 $2)
  48.     local _ADD_PAD=0
  49.     local _ADD_CAR=0
  50.     local _ADD_TOT=""
  51.     local _ADD_LEN=(${#_ADD_NUM[0]} ${#_ADD_NUM[1]})
  52.     local a=0
  53.     if [[ ${_ADD_LEN[0]} -gt ${_ADD_LEN[1]} ]]; then
  54.         _ADD_PAD=$((_ADD_LEN[0] - 1))
  55.     else
  56.         _ADD_PAD=$((_ADD_LEN[1] - 1))
  57.     fi
  58.  
  59.     for ((a=_ADD_LEN[0]; a<=_ADD_PAD ; a++)); do
  60.         _ADD_NUM[0]=0${_ADD_NUM[0]}
  61.     done
  62.     for ((a=_ADD_LEN[1]; a<=_ADD_PAD ; a++)); do
  63.         _ADD_NUM[1]=0${_ADD_NUM[1]}
  64.     done
  65.     for ((a=_ADD_PAD; a>=0 ; a--)); do
  66.         _ADD_CAR=$((_ADD_CAR + ${_ADD_NUM[0]:$a:1} + ${_ADD_NUM[1]:$a:1}))
  67.         _ADD_TOT=${_ADD_CAR:(-1)}$_ADD_TOT
  68.         _ADD_CAR=${_ADD_CAR:0:(-1)}
  69.         if [[ -z "$_ADD_CAR" ]]; then
  70.             _ADD_CAR=0
  71.         fi
  72.     done
  73.     if [[ $_ADD_CAR -gt 0 ]]; then
  74.         _ADD_TOT=$_ADD_CAR$_ADD_TOT
  75.     fi
  76.     echo $_ADD_TOT
  77. }
  78.  
  79.  
  80. function str_sub
  81. {
  82.     local _SUB_NUM=($1 $2)
  83.     local _SUB_CHA=""
  84.     local _SUB_RES=""
  85.     local _SUB_TAKE=""
  86.     local _SUB_PAD=""
  87.     local _SUB_TOT=""
  88.     local _SUB_LEN=(${#_SUB_NUM[0]} ${#_SUB_NUM[1]})
  89.     if [[ ${_SUB_LEN[0]} -gt ${_SUB_LEN[1]} ]]; then
  90.         _SUB_PAD=$((_SUB_LEN[0] - 1))
  91.     else
  92.         _SUB_PAD=$((_SUB_LEN[1] - 1))
  93.     fi
  94.     for ((a=_SUB_LEN[0]; a<=_SUB_PAD ; a++)); do
  95.         _SUB_NUM[0]=0${_SUB_NUM[0]}
  96.     done
  97.     for ((a=_SUB_LEN[1]; a<=_SUB_PAD ; a++)); do
  98.         _SUB_NUM[1]=0${_SUB_NUM[1]}
  99.     done
  100.     for ((a=_SUB_PAD; a>=0 ; a--)); do
  101.         _SUB_RES=$(( ${_SUB_NUM[0]:$a:1} - ${_SUB_NUM[1]:$a:1} ))
  102.         if [[ $_SUB_RES -lt 0 ]]; then
  103.             _SUB_TAKE=
  104.             for ((b=a; b>=0; b--)); do
  105.                 if [[ $a -ne $b ]]; then
  106.                     if [[ -z "$_SUB_TAKE" ]]; then
  107.                         if [[ "${_SUB_NUM[0]:$b:1}" != "0" ]]; then
  108.  
  109.                             _SUB_CHA=$((${_SUB_NUM[0]:$b:1} - 1))
  110.                             _SUB_TAKE=$((b + 1))
  111.                             _SUB_NUM[0]=${_SUB_NUM[0]:0:$b}$_SUB_CHA${_SUB_NUM[0]:$_SUB_TAKE}
  112.                             _SUB_RES=$(( 1${_SUB_NUM[0]:$a:1} - ${_SUB_NUM[1]:$a:1} ))
  113.                         else
  114.                             _SUB_CHA=$((b + 1))
  115.                             _SUB_NUM[0]=${_SUB_NUM[0]:0:$b}9${_SUB_NUM[0]:$_SUB_CHA}
  116.                         fi
  117.                     fi
  118.                 fi
  119.             done
  120.         fi
  121.         _SUB_TOT=$_SUB_RES$_SUB_TOT
  122.     done
  123.     while [[ "${_SUB_TOT:0:1}" == "0" ]]; do
  124.         _SUB_TOT=${_SUB_TOT:1}
  125.     done
  126.     if [[ -z $_SUB_TOT ]]; then
  127.         _SUB_TOT=0
  128.     fi
  129.     echo $_SUB_TOT
  130. }
  131.  
  132.  
  133. function str_mult
  134. {
  135.     local _MUL_NUM=($1 $2)
  136.     local _MUL_CAR=0
  137.     local _MUL_TOT=0
  138.     local _MUL_ROW=""
  139.     local _MUL_X10=""
  140.     local _MUL_REV=("" "")
  141.     for a in 0 1; do
  142.         for ((b=0; b<${#_MUL_NUM[$a]}; b++)); do
  143.             _MUL_REV[$a]=${_MUL_NUM[$a]:$b:1}\ ${_MUL_REV[$a]}
  144.         done
  145.     done
  146.     for a in ${_MUL_REV[0]}; do
  147.         _MUL_ROW=$_MUL_X10
  148.         for b in ${_MUL_REV[1]}; do
  149.             _MUL_CAR=$(( (a * b) + _MUL_CAR ))
  150.             _MUL_ROW=${_MUL_CAR:(-1)}$_MUL_ROW
  151.             _MUL_CAR=${_MUL_CAR:0:(-1)}
  152.  
  153.             if [[ -z "$_MUL_CAR" ]]; then
  154.                 _MUL_CAR=0
  155.             fi
  156.         done
  157.         if [[ -n "${_MUL_CAR//0/}${_MUL_ROW//0/}" ]]; then
  158.             #may need to remove leading zeros
  159.             _MUL_TOT=$(str_add $_MUL_CAR$_MUL_ROW $_MUL_TOT)
  160.         fi
  161.         _MUL_CAR=0
  162.         _MUL_X10=0$_MUL_X10
  163.      done
  164.     echo "$_MUL_TOT"
  165. }
  166.  
  167.  
  168. function str_div
  169. {
  170.     local _DIV_PAD=""
  171.     local _DIV_X10=""
  172.     local _DIV_DONE=0
  173.     local _DIV_TOT=0
  174.     if [[ -z "$4" ]]; then
  175.         for ((a=1; a<=$3; a++)); do
  176.             _DIV_PAD=0$_DIV_PAD
  177.         done
  178.     fi
  179.     local _DIV_NUM=($1$_DIV_PAD $2)
  180.     while [[ "${_DIV_NUM[0]:0:1}" == "0" ]]; do
  181.         _DIV_NUM[0]=${_DIV_NUM[0]:1}
  182.     done
  183.     while [[ "${_DIV_NUM[1]:0:1}" == "0" ]]; do
  184.         _DIV_NUM[1]=${_DIV_NUM[1]:1}
  185.     done
  186.  
  187.     for ((a=${#_DIV_NUM[1]}; a<${#_DIV_NUM[0]}; a++)); do
  188.         _DIV_X10=0$_DIV_X10
  189.     done
  190.     while [[ "$_DIV_DONE" == "0" ]]; do
  191.         isgreater "${_DIV_NUM[0]}" "${_DIV_NUM[1]}$_DIV_X10"
  192.         if [[ $? -le 2 ]]; then
  193.             _DIV_NUM[0]=$(str_sub "${_DIV_NUM[0]}" "${_DIV_NUM[1]}$_DIV_X10")
  194.             _DIV_TOT=$(str_add $_DIV_TOT 1$_DIV_X10)
  195.         elif [[ -n "$_DIV_X10" ]]; then
  196.             _DIV_X10=${_DIV_X10:1}
  197.         else
  198.             _DIV_DONE=1
  199.         fi
  200.     done
  201.     if [[ -n "$4" ]]; then
  202.         _DIV_TOT=${_DIV_NUM[0]}
  203.     fi
  204.     echo "$_DIV_TOT"
  205. }
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212. function str_exp
  213. {
  214.  
  215.     local _EXP_SRL=""
  216.     local _EXP_SQU=$2
  217.     local _EXP_TOT=$1
  218.     local _EXP_PRC=1
  219.  
  220.     while [[ $_EXP_PRC -eq 1 ]]; do
  221.         _EXP_SQU+="0"
  222.         _EXP_SQU=$(str_div "$_EXP_SQU" "2" "0")
  223.         if [[ "${_EXP_SQU:(-1)}" == "5" ]]; then
  224.             _EXP_SRL+=" $_EXP_TOT"
  225.         fi
  226.         _EXP_SQU=${_EXP_SQU:0:(-1)}
  227.         if [[ -z "$_EXP_SQU" ]]; then
  228.             _EXP_PRC=0
  229.         else            
  230.             _EXP_TOT=$(str_mult "$_EXP_TOT" "$_EXP_TOT")
  231.             if [[ "$_EXP_SQU" == "3" ]]; then
  232.                 _EXP_SRL+=" $_EXP_TOT"
  233.                 _EXP_SQU=2
  234.             fi
  235.             if [[ "$_EXP_SQU" == "2" ]]; then
  236.                 _EXP_TOT=$(str_mult "$_EXP_TOT" "$_EXP_TOT")
  237.                 for remaining in $_EXP_SRL; do
  238.                     _EXP_TOT=$(str_mult "$_EXP_TOT" "$remaining")
  239.                 done
  240.                 _EXP_PRC=0
  241.             fi
  242.             if [[ "$_EXP_SQU" == "1" ]]; then
  243.                 _EXP_PRC=0
  244.             fi
  245.         fi
  246.     done
  247.     echo "$_EXP_TOT"
  248.  
  249. }
  250.  
  251.  
  252.  
  253.  
  254.  
  255. ################################################################################
  256. ################################## Main script #################################
  257. ################################################################################
  258.  
  259.  
  260. if [[ -z "$3" ]]; then
  261.     echo
  262.     echo "STR_MATH BASH version bv1.2"
  263.     echo
  264.     echo "   Large number and floating point work around script for Addition,"
  265.     echo "   Subtraction, Division, Multiplaction, Modulus and exponents."
  266.     echo "   Floating point and negative numbers supported."
  267.     echo
  268.     echo "   Usage:"
  269.     echo "     STR_MATH {Number} {+-XM} {Number}"
  270.     echo "     STR_MATH {Number} {/Y} {Number} [n max decimal places]"
  271.     echo
  272.     echo "   Division and certain negative exponents default to a maximum"
  273.     echo "   of ten decimal places of output. An optional user defined max"
  274.     echo "   can be input as the fourth number when applicable."
  275.     echo
  276.     echo "   No rounding is performed on output of division, the number"
  277.     echo "   is only truncated. For example a result of 0.1257 with three"
  278.     echo "   places will return 0.125 NOT 0.126."
  279.     echo
  280.     echo "   Square brackets can be used on negative base exponents instead"
  281.     echo "   of parentheses if needed:"
  282.     echo "      STR_MATH [-5] Y 10"
  283.     echo "      STR_MATH -5 Y 10"
  284.     echo
  285.     echo "   Fractional exponents are not supported."
  286.     echo
  287.     echo "   Results are not garanteed. This script is AS-IS."
  288.     echo
  289.     echo "   Output Will be echo'd"
  290.     echo
  291.     echo "Judago 2016"
  292.     echo
  293.     exit
  294. fi
  295.  
  296. _VAR_TMP=""
  297. _INP_NEG=("" "")
  298. _INP_DP=(0 0)
  299. _OUT_DP=""
  300. _OUT_NEG=
  301. _INP_NUM=("$1" "$3")
  302. _INP_OP="$2"
  303. _INP_EXP_PAR=0
  304. _INP_EXP_DIV=0
  305.  
  306. #Default number of decimal places for division
  307. _DIV_DP=10
  308.  
  309.  
  310.  
  311. ################################################################################
  312. ############################### Input validation ###############################
  313. ################################################################################
  314.  
  315.  
  316.  
  317. ###### Validate the operator.
  318. if [[ "$_INP_OP" == "*" ]]; then
  319.     _INP_OP=X
  320. fi
  321. if [[ "$_INP_OP" == "%" ]]; then
  322.     _INP_OP=M
  323. fi
  324. _INP_OP=${_INP_OP//y/Y}
  325. _INP_OP=${_INP_OP//m/M}
  326. _INP_OP=${_INP_OP//x/X}
  327. if [[ ${#_INP_OP} -ne 1 || -n "${_INP_OP//[\/X+MY\-]/}" ]]; then
  328.     1>&2 echo "ERROR: Bad operator: " "$*"
  329.     exit
  330. fi
  331.  
  332.  
  333. ###### Only 3 arguments should be available, except for the optional decimal
  334. ###### places for division, where 4 can be used.
  335. if [[ -n "${_INP_OP//[\/Y]/}" && -n "$4" ||  -z "${_INP_OP//[\/Y]}" && -n "$5" ]]; then
  336.     1>&2 echo "ERROR: Too many arguments: " "$*"
  337.     exit
  338. fi
  339.  
  340.  
  341. ###### Fractional exponents aren't supported
  342. if [[ "${_INP_OP}" == "Y" && "${_INP_NUM[0]//./}${_INP_NUM[1]//./}" != "${_INP_NUM[0]}${_INP_NUM[1]}" ]]; then
  343.     1>&2 echo "ERROR: Fractional exponents are not supported"
  344.     exit
  345. fi
  346.  
  347. ###### Test for paranthisis on input negative exponent
  348. if [[ "${_INP_OP}" == "Y" && -n "${_INP_NUM[0]}" ]]; then
  349.     if [[ "${_INP_NUM[0]//[\[\]]/}" != "${_INP_NUM[0]}" ]]; then
  350.         _INP_EXP_PAR=1
  351.         _INP_NUM[0]="${_INP_NUM[0]//[\[\]]/}"
  352.     fi
  353. fi
  354.  
  355.  
  356. ###### Validate input numbers
  357. for i in 0 1; do
  358.     if [[   ! "${_INP_NUM[$i]}" =~ ^[0-9]*$
  359.        &&   ! "${_INP_NUM[$i]}" =~ ^-[0-9]*$
  360.        &&   ! "${_INP_NUM[$i]}" =~ ^[0-9]*\.[0-9]*$
  361.        &&   ! "${_INP_NUM[$i]}" =~ ^-[0-9]*\.[0-9]*$
  362.     ]]
  363.     then
  364.         1>&2 echo "ERROR: Invalid input: " "$*"
  365.         exit
  366.     fi
  367.     #negative
  368.     if [[ "${_INP_NUM[$i]//-/}" != "${_INP_NUM[$i]}" ]]; then
  369.         if [[ ${#_INP_NUM[$i]} -eq 1 ]]; then
  370.             1>&2 echo "ERROR: Invalid input: " "$*"
  371.             exit
  372.         else
  373.             _INP_NUM[$i]=${_INP_NUM[$i]:1}
  374.             _INP_NEG[$i]=-
  375.         fi
  376.     fi
  377.     #decimal point
  378.     if [[ "${_INP_NUM[$i]//\./}" != "${_INP_NUM[$i]}" ]]; then
  379.         if [[ ${#_INP_NUM[$i]} -eq 1 ]]; then
  380.             1>&2 echo "ERROR: Invalid input: " "$*"
  381.             exit
  382.         fi
  383.     fi
  384. done
  385.  
  386.  
  387. ################################################################################
  388. ################################ Input parsing #################################
  389. ################################################################################
  390.  
  391.  
  392. ###### Change number of decimal places for division/negative exponents if requested. Strip leading zeros, if any.
  393. if [[ -z "${_INP_OP//[\/Y]/}" && -n "$4" ]]; then
  394.     if [[ -z "${4//[0-9]/}" ]]; then
  395.         _DIV_DP="$4"
  396.         while [[ "${_DIV_DP:0:1}" == "0" ]]; do
  397.             _DIV_DP=${_DIV_DP:1}
  398.         done
  399.         if [[ -z $_DIV_DP ]]; then
  400.             _DIV_DP=0
  401.         fi
  402.     else
  403.         1>&2 echo "ERROR: Invalid input: " "$*"
  404.         exit
  405.     fi
  406. fi
  407.  
  408.  
  409. ###### Remove leading zero, return for sums including zero and get position of decimal places
  410. for i in 0 1 ; do
  411.  
  412.     #Remove leading zeros
  413.     while [ "${_INP_NUM[$i]:0:1}" == "0" ]; do
  414.         _INP_NUM[$i]=${_INP_NUM[$i]:1}
  415.     done
  416.  
  417.     #Ensure the input is populated and has a leading and trailing zero for floating point.
  418.     if [[ -z "${_INP_NUM[$i]}" ]]; then
  419.         _INP_NUM[$i]=0
  420.     fi
  421.     if [[ "${_INP_NUM[$i]:0:1}" == "." ]]; then
  422.         _INP_NUM[$i]=0${_INP_NUM[$i]}
  423.     fi
  424.     if [[ "${_INP_NUM[$i]:-1}" == "." ]]; then
  425.         _INP_NUM[$i]=${_INP_NUM[$i]}0
  426.     fi
  427.  
  428.     # Return for zero sums
  429.     if [[ "${_INP_NUM[$i]}" == "0" ]]; then
  430.         if [[ "$_INP_OP" == "X" ]]; then
  431.             echo "0"
  432.         elif [[ "$_INP_OP" == "/" || "$_INP_OP" == "M" ]]; then
  433.             if [[ $i -eq 1 ]]; then
  434.                 1>&2 echo "ERROR: Divide by zero"
  435.             else
  436.                 if [[ ${_INP_NUM[1]} -eq 0 ]]; then
  437.                     1>&2 echo "ERROR: Divide by zero"
  438.                     exit
  439.                 fi
  440.                 echo "0"
  441.             fi
  442.         elif [[ "$_INP_OP" == "-" ]]; then
  443.             if [[ $i -eq 0 ]]; then
  444.                 if [[ -n ${_INP_NEG[1]} ]]; then
  445.                     echo ${_INP_NUM[1]}
  446.                 else
  447.                     echo -${_INP_NUM[1]}
  448.                 fi
  449.             else
  450.                 echo ${_INP_NEG[0]}${_INP_NUM[0]}
  451.             fi
  452.         elif [[ "$_INP_OP" == "+" ]]; then
  453.             if [[ $i -eq 0 ]]; then
  454.                 echo ${_INP_NEG[1]}${_INP_NUM[1]}
  455.             else
  456.                 echo ${_INP_NEG[0]}${_INP_NUM[0]}
  457.             fi
  458.  
  459.         elif [[ "$_INP_OP" == "Y" ]]; then
  460.             if [[ $i -eq 0 ]]; then
  461.                 if [[ -n "${_INP_NEG[1]}" ]]; then
  462.                     1>&2 echo "ERROR: Negative exponents of zero are undefined."
  463.                 else
  464.                     echo 0
  465.                 fi
  466.             else
  467.                 if [[ $_INP_EXP_PAR -eq 1 ]]; then
  468.                     echo 1
  469.                 else
  470.                     echo "${_INP_NEG[0]}1"
  471.                 fi
  472.             fi
  473.  
  474.         fi
  475.         exit
  476.     fi
  477.     #get position of decimal point
  478.     if [[ "${_INP_NUM[$i]//./}" != "${_INP_NUM[$i]}" ]]; then
  479.         for ((j=${#_INP_NUM[$i]} - 1; j>=0; j--)); do
  480.             if [[ "${_INP_NUM[$i]:$j:1}" == "." ]]; then
  481.                 _INP_DP[$i]=$((${#_INP_NUM[$i]} - (j + 1)))
  482.             fi
  483.         done
  484.     fi
  485. done
  486.  
  487.  
  488. ###### Floating point normalisation
  489. _INP_NUM[0]=${_INP_NUM[0]//./}
  490. _INP_NUM[1]=${_INP_NUM[1]//./}
  491. if [[ ${_INP_DP[0]} -gt ${_INP_DP[1]} ]]; then
  492.     _OUT_DP=$((_INP_DP[0] - 1))
  493. else
  494.     _OUT_DP=$((_INP_DP[1] - 1))
  495. fi
  496.  
  497. for ((i=_INP_DP[0]; i<=_OUT_DP; i++)); do
  498.     _INP_NUM[0]=${_INP_NUM[0]}0
  499. done
  500. for ((i=_INP_DP[1]; i<=_OUT_DP; i++)); do
  501.     _INP_NUM[1]=${_INP_NUM[1]}0
  502. done
  503.  
  504.  
  505. ###### Check for negative output, alter operator and set final negative output.
  506. if [[ "$_INP_OP" == "X" ]]; then
  507.     if [[ "${_INP_NEG[0]}${_INP_NEG[1]}" == "-" ]]; then
  508.         _OUT_NEG=-
  509.     fi
  510. elif [[ "$_INP_OP" == "+" ]]; then
  511.     if [[ "${_INP_NEG[0]}${_INP_NEG[1]}" == "--" ]]; then
  512.         _OUT_NEG=-
  513.     fi
  514.     if [[ -n "${_INP_NEG[1]}" && -z "${_INP_NEG[0]}" ]]; then
  515.         isgreater ${_INP_NUM[0]} ${_INP_NUM[1]}
  516.         if [[ $? -eq 3 ]]; then
  517.             _OUT_NEG=-
  518.             _VAR_TMP=${_INP_NUM[0]}
  519.             _INP_NUM[0]=${_INP_NUM[1]}
  520.             _INP_NUM[1]=$_VAR_TMP
  521.         fi
  522.         _INP_OP=-
  523.     fi
  524.     if [[ -n "${_INP_NEG[0]}" && -z "${_INP_NEG[1]}" ]]; then
  525.         isgreater ${_INP_NUM[0]} ${_INP_NUM[1]}
  526.         if [[ $? -eq 3 ]]; then
  527.             _VAR_TMP=${_INP_NUM[0]}
  528.             _INP_NUM[0]=${_INP_NUM[1]}
  529.             _INP_NUM[1]=$_VAR_TMP
  530.         elif [[ %? -eq 1 ]]; then
  531.             _OUT_NEG=-
  532.         fi
  533.         _INP_OP=-
  534.     fi
  535. elif [[ "$_INP_OP" == "-" ]]; then
  536.     if [[ "${_INP_NEG[0]}${_INP_NEG[1]}" == "" ]]; then
  537.         isgreater ${_INP_NUM[0]} ${_INP_NUM[1]}
  538.         if [[ "$?" == "3" ]]; then
  539.             _OUT_NEG=-
  540.             _VAR_TMP=${_INP_NUM[0]}
  541.             _INP_NUM[0]=${_INP_NUM[1]}
  542.             _INP_NUM[1]=$_VAR_TMP
  543.         fi
  544.     fi
  545.     if [[ "${_INP_NEG[0]}${_INP_NEG[1]}" == "--" ]]; then
  546.         isgreater ${_INP_NUM[0]} ${_INP_NUM[1]}
  547.         if [[ "$?" == "3" ]]; then
  548.             _VAR_TMP=${_INP_NUM[0]}
  549.             _INP_NUM[0]=${_INP_NUM[1]}
  550.             _INP_NUM[1]=_$_VAR_TMP
  551.         elif [[ %? -eq 1 ]]; then
  552.             _OUT_NEG=-
  553.         fi
  554.     fi
  555.     if [[ -n "${_INP_NEG[1]}" && -z "${_INP_NEG[0]}" ]]; then
  556.         _INP_OP=+
  557.    fi
  558.     if [[ -n "${_INP_NEG[0]}" && -z "${_INP_NEG[1]}" ]]; then
  559.         _INP_OP=+
  560.         _OUT_NEG=-
  561.     fi
  562. elif [[ "$_INP_OP" == "/" ]]; then
  563.     if [[ "${_INP_NEG[0]}${_INP_NEG[1]}" == "--" ]]; then
  564.         _OUT_NEG=""
  565.     fi
  566.     if [[ "${_INP_NEG[0]}${_INP_NEG[1]}" == "-" ]]; then
  567.         _OUT_NEG=-
  568.     fi
  569. elif [[ "$_INP_OP" == "M" ]]; then
  570.     if [[ -n "${_INP_NEG[0]}" ]]; then
  571.         _OUT_NEG=-
  572.     fi
  573. elif [[ "$_INP_OP" == "Y" ]]; then
  574.     if [[ $_INP_EXP_PAR -eq 0 ]]; then
  575.         if [[ "${_INP_NEG[0]}${_INP_NEG[1]}" == "--" ]]; then
  576.             _OUT_NEG=-
  577.             _INP_EXP_DIV=1
  578.         elif [[ -n "${_INP_NEG[1]}" ]]; then
  579.             _INP_EXP_DIV=1
  580.         elif [[ -n "${_INP_NEG[0]}" ]]; then
  581.             _OUT_NEG=-
  582.         fi
  583.     else
  584.         if [[ "${_INP_NEG[0]}${_INP_NEG[1]}" == "--" ]]; then
  585.             if [[ "${_INP_NUM[1]:(-1)}" =~ [13579] ]]; then
  586.                 _OUT_NEG=-
  587.             fi
  588.             _INP_EXP_DIV=1
  589.         elif [[ -n "${_INP_NEG[1]}" ]]; then
  590.             _OUT_NEG=-
  591.             _INP_EXP_DIV=1
  592.         elif [[ -n "${_INP_NEG[0]}" ]]; then
  593.             if [[ "${_INP_NUM[1]:(-1)}" =~ [13579] ]]; then
  594.                 _OUT_NEG=-
  595.             fi
  596.         fi
  597.     fi
  598. fi
  599.  
  600.  
  601. ################################################################################
  602. ####################### Call the appropiate subroutines ########################
  603. ################################################################################
  604.  
  605.  
  606. #Numbers are now validated and normalised, _OUT_NEG shows if the result is negative
  607. #_OUT_DP holds the number of decimal places
  608.  
  609. ######Pass the numbers
  610.  
  611.  
  612.  
  613.  
  614. if [[ "$_INP_OP" == "+" ]]; then
  615.     _FIN_NUM=$(str_add ${_INP_NUM[0]} ${_INP_NUM[1]})
  616. elif [[ "$_INP_OP" == "-" ]]; then
  617.     _FIN_NUM=$(str_sub ${_INP_NUM[0]} ${_INP_NUM[1]})
  618. elif [[ "$_INP_OP" == "X" ]]; then
  619.     _OUT_DP=$(( (_OUT_DP * 2) + 1 ))
  620.     _FIN_NUM=$(str_mult ${_INP_NUM[0]} ${_INP_NUM[1]})
  621. elif [[ "$_INP_OP" == "/" ]]; then
  622.     _FIN_NUM=$(str_div ${_INP_NUM[0]} ${_INP_NUM[1]} $_DIV_DP)
  623.     _OUT_DP=$((_DIV_DP - 1))
  624. elif [[ "$_INP_OP" == "M" ]]; then
  625.     _FIN_NUM=$(str_div ${_INP_NUM[0]} ${_INP_NUM[1]} $_DIV_DP MOD)
  626. elif [[ "$_INP_OP" == "Y" ]]; then
  627.     _FIN_NUM=$(str_exp ${_INP_NUM[0]} ${_INP_NUM[1]})
  628.     if [[ $_INP_EXP_DIV -eq 1 ]]; then
  629.         _FIN_NUM=$(str_div "1" $_FIN_NUM $_DIV_DP)
  630.         _OUT_DP=$((_DIV_DP - 1))
  631.     fi
  632. fi
  633.  
  634.  
  635.  
  636. ######Reintroduce the decimal point, strip leading zeros and trailing zeros for decimal numbers and echo the result
  637. if [[ -z "$_OUT_DP" ]]; then
  638.     _OUT_DP=0
  639. else
  640.     _OUT_DP=$((_OUT_DP + 1))
  641. fi
  642. if [[ "$_OUT_DP" != "0" ]]; then
  643.     for ((i=1; i<=_OUT_DP; i++)); do
  644.         if [[ -z "${_FIN_NUM:$_OUT_DP}" ]]; then
  645.             _FIN_NUM=0$_FIN_NUM
  646.         fi
  647.     done
  648.     _FIN_NUM=${_FIN_NUM:0:-$_OUT_DP}.${_FIN_NUM:(-$_OUT_DP)}
  649.     for ((i=_OUT_DP; i>=0; i--)); do
  650.         if [[ "${_FIN_NUM:(-1)}" == "0" || "${_FIN_NUM:(-1)}" == "." ]]; then
  651.             _FIN_NUM=${_FIN_NUM:0:-1}
  652.         fi
  653.     done
  654. fi
  655.  
  656. while [ "${_FIN_NUM:0:1}" == "0" ]; do
  657.     _FIN_NUM=${_FIN_NUM:1}
  658. done
  659. if [[ -z "${_FIN_NUM}" ]]; then
  660.         _FIN_NUM=0
  661. fi
  662. if [ "${_FIN_NUM:0:1}" == "." ]; then
  663.     _FIN_NUM=0$_FIN_NUM
  664. fi
  665. echo $_OUT_NEG$_FIN_NUM
  666. exit
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement