Hi,
  Please say something if this patch should be sent someplace else.
  Shellmath's "runTests.sh" script returned x8 failing tests. This patch
addresses all eight errors as well as shellcheck's various complaints. The
full test suite now passes. These specific changes have been addressed:

* doc/bash/examples/shellmath/shellmath.sh
  + Remove trailing spaces and tabs.
  + Workaround of problematic use of "10#$fractionalSum" syntax by
replacing it with an admittedly awkward
"${fractionalSum//[^-]}10#${fractionalSum//[^0-9]}" expansion syntax. For
example, `echo $(( 10#-3 ))` fails while `echo $(( -10#3 ))` succeeds.
  + Changed a parameter expansion on line ~546 to remove just a hyphen
rather than any initial character.
  + The new expansion syntax obviated the need for a code block at line
~485; comment amended.
  + Per shellcheck:
    + "SC2295 (info): Expansions inside ${..} need to be quoted separately,
otherwise they match as patterns.", at lines 668, 670 and 1066
    + "SC2086 (info): Double quote to prevent globbing and word
splitting.", at lines 562, 1046 and 1051.
      + for SC2086, lines 165, 166 are false positives (re use of `eval`).
    + "SC2059 (info): Don't use variables in the printf format string. Use
printf '..%s..' "$foo"," at line 91.
    + "SC2004 (style): $/${} is unnecessary on arithmetic variables," at
line 826.

The original set of testing errors:
'''
$ bash ./runTests.sh
...
ok  Line 55: String 3.8    add 1.9 1.9
shellmath.sh: line 518: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 530: ((: integerSum < 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 533: ((: integerSum > 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 539: ((: integerSum == 0 && 10#: invalid integer
constant (error token is "10#")
shellmath.sh: line 546: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 550: ((: 10#: invalid integer constant (error token is
"10#")
FAIL (-2)  Line 56: String -3.8    add -1.9 -1.9
ok  Line 59: String 2.195    add 1.105 1.09
shellmath.sh: line 518: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 530: ((: integerSum < 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 533: ((: integerSum > 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 539: ((: integerSum == 0 && 10#: invalid integer
constant (error token is "10#")
shellmath.sh: line 546: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 550: ((: 10#: invalid integer constant (error token is
"10#")
FAIL (-2)  Line 60: String -2.195    add -1.105 -1.09
ok  Line 63: String 2.014    add 1.005 1.009
shellmath.sh: line 518: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 530: ((: integerSum < 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 533: ((: integerSum > 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 539: ((: integerSum == 0 && 10#: invalid integer
constant (error token is "10#")
shellmath.sh: line 546: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 550: ((: 10#: invalid integer constant (error token is
"10#")
FAIL (-2)  Line 64: String -2.014    add -1.005 -1.009
ok  Line 66: String 3.31462    add 1.905 1.40962
ok  Line 67: String 2.01462    add 1.005 1.00962
shellmath.sh: line 518: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 530: ((: integerSum < 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 533: ((: integerSum > 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 539: ((: integerSum == 0 && 10#: invalid integer
constant (error token is "10#")
shellmath.sh: line 546: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 550: ((: 10#: invalid integer constant (error token is
"10#")
FAIL (3)  Line 70: String 2.5   subtract 5.2 2.7
shellmath.sh: line 539: ((: integerSum == 0 && 10#: invalid integer
constant (error token is "10#")
shellmath.sh: line 546: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 550: ((: 10#: invalid integer constant (error token is
"10#")
FAIL (-2)  Line 71: String -2.5   subtract 2.7 5.2
shellmath.sh: line 518: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 530: ((: integerSum < 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 533: ((: integerSum > 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 539: ((: integerSum == 0 && 10#: invalid integer
constant (error token is "10#")
shellmath.sh: line 546: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 550: ((: 10#: invalid integer constant (error token is
"10#")
FAIL (3)  Line 72: String 2.5   add 5.2 -2.7
ok  Line 75: String 1.5  add 0.6 0.9
ok  Line 76: String 1.5  add .6 .9
shellmath.sh: line 518: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 530: ((: integerSum < 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 533: ((: integerSum > 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 539: ((: integerSum == 0 && 10#: invalid integer
constant (error token is "10#")
shellmath.sh: line 546: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 550: ((: 10#: invalid integer constant (error token is
"10#")
FAIL (0)  Line 77: String -0.3 add 0.6 -0.9
shellmath.sh: line 518: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 530: ((: integerSum < 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 533: ((: integerSum > 0 && 10#: invalid integer constant
(error token is "10#")
shellmath.sh: line 539: ((: integerSum == 0 && 10#: invalid integer
constant (error token is "10#")
shellmath.sh: line 546: ((: 10#: invalid integer constant (error token is
"10#")
shellmath.sh: line 550: ((: 10#: invalid integer constant (error token is
"10#")
FAIL (0)  Line 78: String -0.3 add .6 -.9
ok  Line 81: String 12     add 2 4 6
...
'''

Patch:
[liveuser@fedora bash-doc_shellmath.sh]$ reset; LC_ALL=C TZ=UTC0 diff -Naur
shellmath.sh-orig shellmath.sh-edited

--- shellmath.sh-orig 2025-02-04 06:33:39.408827191 +0000
+++ shellmath.sh-edited 2025-02-05 01:23:59.319374175 +0000
@@ -18,7 +18,7 @@
 #    _shellmath_add 44.2 -87
 #    _shellmath_getReturnValue mySum
 #    echo $mySum
-#
+#
 
################################################################################


@@ -85,10 +85,10 @@
     returnCode=${BASH_REMATCH[1]}
     msgTemplate=${BASH_REMATCH[2]}
     shift
-
+
     # Display error msg, making parameter substitutions as needed
     msgParameters="$*"
-    printf  "$msgTemplate" "${msgParameters[@]}"
+    printf '%s ' "$msgTemplate" "${msgParameters[@]}"; printf '\n'

     if ((returnDontExit)); then
         return "$returnCode"
@@ -181,7 +181,7 @@
     local numericType returnCode

     ((returnCode = __shellmath_SUCCESS))
-
+
     # Accept decimals: leading digits (optional), decimal point, trailing
digits
     if [[ "$n" =~ ^[-]?([0-9]*)\.([0-9]+)$ ]]; then
         local integerPart=${BASH_REMATCH[1]:-0}
@@ -442,7 +442,7 @@
         ((isNegative2)) && ((integerPart2*=-1))
         local sum=$((integerPart1 + integerPart2))
         if (( (!isSubcall) && (isScientific1 || isScientific2) )); then
-            _shellmath_numToScientific $sum ""
+            _shellmath_numToScientific $sum ""
             _shellmath_getReturnValue sum
         fi
         _shellmath_setReturnValue $sum
@@ -485,17 +485,11 @@
     # Summing the fractional parts is tricky: We need to override the
shell's
     # default interpretation of leading zeros, but the operator for doing
this
     # (the "10#" operator) cannot work directly with negative numbers. So
we
-    # break it all down.
-    if ((isNegative1)); then
-        ((fractionalSum += (-1) * 10#${fractionalPart1:1}))
-    else
-        ((fractionalSum += 10#$fractionalPart1))
-    fi
-    if ((isNegative2)); then
-        ((fractionalSum += (-1) * 10#${fractionalPart2:1}))
-    else
-        ((fractionalSum += 10#$fractionalPart2))
-    fi
+    # use parameter expansions to separate the \+/-\ signs from the
numbers.
+
+    ((fractionalSum =
+        ${fractionalPart1//[^-]}10#${fractionalPart1//[^0-9]} +
+        ${fractionalPart2//[^-]}10#${fractionalPart2//[^0-9]}))

     unsignedFracSumLength=${#fractionalSum}
     if [[ "$fractionalSum" =~ ^[-] ]]; then
@@ -515,7 +509,9 @@
     fi

     # Carry a digit from fraction to integer if required
-    if ((10#$fractionalSum!=0 && unsignedFracSumLength >
unsignedFracLength)); then
+    if (( ${fractionalSum//[^-]}10#${fractionalSum//[^0-9]} !=0 )) &&
+        ((unsignedFracSumLength > unsignedFracLength))
+    then
         local carryAmount
         ((carryAmount = isNegative1?-1:1))
         ((integerSum += carryAmount))
@@ -527,34 +523,43 @@
     # pair (-2,3) is not -2.3 but rather (-2)+(0.3), i.e. -1.7 so we want
to
     # transform (-2,3) to (-1,7). This transformation is meaningful when
     # the two parts have opposite signs, so that's what we look for.
-    if ((integerSum < 0 && 10#$fractionalSum > 0)); then
+    if ((integerSum < 0)) &&
+        (( ${fractionalSum//[^-]}10#${fractionalSum//[^0-9]} > 0))
+    then
         ((integerSum += 1))
-        ((fractionalSum = 10#$fractionalSum - 10**unsignedFracSumLength))
-    elif ((integerSum > 0 && 10#$fractionalSum < 0)); then
+        ((fractionalSum =
${fractionalSum//[^-]}10#${fractionalSum//[^0-9]} -
+            10**unsignedFracSumLength))
+    elif ((integerSum > 0)) &&
+        (( ${fractionalSum//[^-]}10#${fractionalSum//[^0-9]} < 0))
+    then
         ((integerSum -= 1))
-        ((fractionalSum = 10**unsignedFracSumLength + 10#$fractionalSum))
+        ((fractionalSum = 10**unsignedFracSumLength +
+            ${fractionalSum//[^-]}10#${fractionalSum//[^0-9]} ))
     fi
     # This last case needs to function either as an "else" for the above,
     # or as a coda to the "if" clause when integerSum is -1 initially.
-    if ((integerSum == 0 && 10#$fractionalSum < 0)); then
+    if ((integerSum == 0)) &&
+        (( ${fractionalSum//[^-]}10#${fractionalSum//[^0-9]} < 0))
+    then
         integerSum="-"$integerSum
         ((fractionalSum *= -1))
     fi

     # Touch up the numbers for display
     local sum
-    ((10#$fractionalSum < 0)) && fractionalSum=${fractionalSum:1}
+    (( ${fractionalSum//[^-]}10#${fractionalSum//[^0-9]}< 0)) &&
+        fractionalSum=${fractionalSum//[-]}
     if (( (!isSubcall) && (isScientific1 || isScientific2) )); then
         _shellmath_numToScientific "$integerSum" "$fractionalSum"
         _shellmath_getReturnValue sum
-    elif ((10#$fractionalSum)); then
+    elif (( ${fractionalSum//[^-]}10#${fractionalSum//[^0-9]} )); then
         printf -v sum "%s.%s" "$integerSum" "$fractionalSum"
     else
         sum=$integerSum
     fi

     # Note the result, print if running "normally", and return
-    _shellmath_setReturnValue $sum
+    _shellmath_setReturnValue "$sum"
     if (( isVerbose && ! isSubcall )); then
         echo "$sum"
     fi
@@ -660,9 +665,9 @@
         fi

         # Discard the least-significant digits or move them past the
decimal point
-        value1=${value1%${tail1}}
+        value1=${value1%"${tail1}"}
         [[ -n "$subvalue1" ]] && subvalue1=${tail1}${subvalue1%0}  #
remove placeholder zero
-        value2=${value2%${tail2}}
+        value2=${value2%"${tail2}"}
         [[ -n "$subvalue2" ]] && subvalue2=${tail2}${subvalue2%0}
     else
         # Signal the caller that no rescaling was actually done
@@ -733,7 +738,7 @@

     number=${number:0:digitCount}
     if ((nextDigit >= 5)); then
-        printf -v number "%0*d" "$digitCount" $((10#$number + 1))
+        printf -v number "%0*d" "$digitCount"
$((${number//[^-]}10#${number//[^0-9]} + 1))
     fi

     _shellmath_setReturnValue "$number"
@@ -818,11 +823,15 @@

     # Overflow / underflow detection and accommodation
     local rescalingFactor=0
-    if ((${#integerPart1} + ${#integerPart2} + ${#fractionalPart1} +
${#fractionalPart2} >= ${__shellmath_precision})); then
+    if ((${#integerPart1} + ${#integerPart2} + ${#fractionalPart1} +
${#fractionalPart2} >= __shellmath_precision)); then
         _shellmath_reduceOuterPairs "$integerPart1" "$integerPart2"
"$fractionalPart1" "$fractionalPart2"
         _shellmath_getReturnValues integerPart1 integerPart2
fractionalPart1 fractionalPart2 rescalingFactor
-        if ((10#$fractionalPart1)); then
type1=${__shellmath_numericTypes[DECIMAL]}; fi
-        if ((10#$fractionalPart2)); then
type2=${__shellmath_numericTypes[DECIMAL]}; fi
+        if ((${fractionalPart1//[^-]}10#${fractionalPart1//[^0-9]})); then
+            type1=${__shellmath_numericTypes[DECIMAL]}
+        fi
+        if ((${fractionalPart2//[^-]}10#${fractionalPart2//[^0-9]})); then
+            type2=${__shellmath_numericTypes[DECIMAL]}
+        fi

         _shellmath_reduceCrossPairs "$integerPart1" "$integerPart2"
"$fractionalPart1" "$fractionalPart2"
         _shellmath_getReturnValues fractionalPart1 fractionalPart2
@@ -841,7 +850,7 @@
             _shellmath_getReturnValue product
         fi
         if (( (!isSubcall) && (isScientific1 || isScientific2) )); then
-            _shellmath_numToScientific $product ""
+            _shellmath_numToScientific $product ""
             _shellmath_getReturnValue product
         fi
         _shellmath_setReturnValue $product
@@ -862,14 +871,16 @@
     fractionalWidth1=${#fractionalPart1}
     fractionalWidth2=${#fractionalPart2}
     ((floatWidth = fractionalWidth1 + fractionalWidth2))
-    ((floatProduct = 10#$fractionalPart1 * 10#$fractionalPart2))
+    ((floatProduct =
+        ${fractionalPart1//[^-]}10#${fractionalPart1//[^0-9]} *
+        ${fractionalPart2//[^-]}10#${fractionalPart2//[^0-9]}))
     if ((${#floatProduct} < floatWidth)); then
         printf -v floatProduct "%0*d" "$floatWidth" "$floatProduct"
     fi

     # Compute the inner products: First integer-multiply, then rescale
-    ((innerProduct1 = integerPart1 * 10#$fractionalPart2))
-    ((innerProduct2 = integerPart2 * 10#$fractionalPart1))
+    ((innerProduct1 = integerPart1 *
${fractionalPart2//[^-]}10#${fractionalPart2//[^0-9]}))
+    ((innerProduct2 = integerPart2 *
${fractionalPart1//[^-]}10#${fractionalPart1//[^0-9]}))

     # Rescale the inner products back to decimals so we can
shellmath_add() them
     if ((fractionalWidth2 <= ${#innerProduct1})); then
@@ -979,7 +990,9 @@
     fi

     # Throw error on divide by zero
-    if ((integerPart2 == 0 && 10#$fractionalPart2 == 0)); then
+    if ((integerPart2 == 0)) &&
+        (( ${fractionalPart2//[^-]}10#${fractionalPart2//[^0-9]} == 0 ))
+    then
         _shellmath_warn  "${__shellmath_returnCodes[DIVIDE_BY_ZERO]}"
 "$n2"
         return $?
     fi
@@ -1002,11 +1015,13 @@
     # Rescale and rewrite the fraction to be computed, and compute it
     numerator=${integerPart1}${fractionalPart1}${zeroTail}
     denominator=${integerPart2}${fractionalPart2}
-    ((quotient = 10#$numerator / 10#$denominator))
+    ((quotient = ${numerator//[^-]}10#${numerator//[^0-9]} /
+        ${denominator//[^-]}10#${denominator//[^0-9]}))

     # For greater precision, re-divide by the remainder to get the next
digits of the quotient
     local remainder quotient_2
-    ((remainder = 10#$numerator % 10#$denominator))   # cannot exceed
numerator or thus, maxValue
+    ((remainder = ${numerator//[^-]}10#${numerator//[^0-9]} %
+        ${denominator//[^-]}10#${denominator//[^0-9]})) # cant exceed
numerator or thus, maxValue
     ((zeroCount = __shellmath_precision - ${#remainder}))
     if ((zeroCount > 0)); then
         printf -v zeroTail "%0*d" "$zeroCount" 0
@@ -1015,7 +1030,8 @@
     fi
     # Derive the new numerator from the remainder. Do not change the
denominator.
     numerator=${remainder}${zeroTail}
-    ((quotient_2 = 10#$numerator / 10#$denominator))
+    ((quotient_2 = ${numerator//[^-]}10#${numerator//[^0-9]} /
+        ${denominator//[^-]}10#${denominator//[^0-9]}))
     quotient=${quotient}${quotient_2}
     ((rescaleFactor += ${#quotient_2}))

@@ -1027,12 +1043,12 @@
             printf -v zeroPrefix "%0*d" "$((rescaleFactor -
${#quotient}))" 0
         fi
         fractionalPart=${zeroPrefix}${quotient}
-        _shellmath_round "$fractionalPart" $__shellmath_precision
+        _shellmath_round "$fractionalPart" "$__shellmath_precision"
         _shellmath_getReturnValue fractionalPart
         quotient="0."${fractionalPart}
     else
         fractionalPart=${quotient:(-$rescaleFactor)}
-        _shellmath_round "$fractionalPart" $__shellmath_precision
+        _shellmath_round "$fractionalPart" "$__shellmath_precision"
         _shellmath_getReturnValue fractionalPart
         quotient=${quotient:0:(-$rescaleFactor)}"."${fractionalPart}
     fi
@@ -1047,7 +1063,7 @@
         if [[ "$quotient" =~ [\.].*0$ ]]; then
             # If the decimal point IMMEDIATELY precedes the 0s, remove
that too
             [[ $quotient =~ [\.]?0+$ ]]
-            quotient=${quotient%${BASH_REMATCH[0]}}
+            quotient=${quotient%"${BASH_REMATCH[0]}"}
         fi
     fi

[liveuser@fedora bash-doc_shellmath.sh]$

Thank you,
Wiley

Reply via email to