walmart calc
From
Michael Sanders@porkchop@invalid.foo to
comp.unix.shell on Sun Nov 2 21:51:38 2025
From Newsgroup: comp.unix.shell
Earlier I was attempting to wrap bc in a friendly way,
but the order of operations kicked my *ss =)
As an example, consider:
echo '2+50%' | bc
(standard_in) 2: syntax error
So why not an attempt closer to a standard, hand-held calc?
You know the kind, just cheap dollar-store calculators.
Likely needs more work, but its a start.
examples...
exp 2+50%
3.00
exp 500*75.3/25%
150600.00
exp -980*3+876%
-28694.40
#!/bin/sh
<<'NOTES'
simple walmart breed of calculator
Michael Sanders 2025
ops: add +, subtract -, multiply *, divide /, percentage %
NOTES
exp() {
e=$(echo "$1" | tr -d '[:space:]') # compress
[ -z "$e" ] && { echo "usage: exp <expression>"; return 1; }
# allow only valid characters
echo "$e" | grep -Eq '^[0-9./+*%-]+$' || { echo "invalid expression"; return 1; }
# reject if % is first or followed by a digit
echo "$e" | grep -Eq '(^%)|%[0-9]' && { echo "invalid expression"; return 1; }
# reject if % is used standalone before operator
echo "$e" | grep -Eq '[0-9]%[+*/-]' && { echo "0"; return 1; }
DEC="${DEC:-2}" # use global $DEC, default 2
tmp=$(awk -v e="$e" -v dec="$DEC" '
function calc(e,dec,res,i,c,sign,t,val,op,n) {
dec = (dec=="") ? 2 : dec
n = length(e)
i = 1
res = 0
sign = 1
op = "+"
while (i <= n) {
c = substr(e,i,1)
if (c=="-" && (i==1 || substr(e,i-1,1) ~ /[\+\-\*\/]/)) {
sign = -1
i++
continue
}
if (c ~ /[0-9.]/) {
t = ""
while (i<=n && substr(e,i,1) ~ /[0-9.]/) { t = t substr(e,i,1); i++ }
val = sign * t
sign = 1
# percentage handling
if (i<=n && substr(e,i,1)=="%") {
if (op=="+" || op=="-") val = res * val / 100
else val = val / 100
i++
}
if (op=="+") res = res + val
else if (op=="-") res = res - val
else if (op=="*") res = res * val
else if (op=="/") res = res / val
} else if (c ~ /[\+\-\*\/]/) {
op = c
i++
} else { i++ }
}
fmt = "%." dec "f"
return sprintf(fmt, res)
}
BEGIN { print calc(e ,dec) }')
y=0
[ -z "$tmp" ] && { y=1; tmp='invalid expression'; }
echo "$tmp"
return $y
}
exp -980*3+876%
# eof
--
:wq
Mike Sanders
--- Synchronet 3.21a-Linux NewsLink 1.2