diff --git a/subtraction/sub b/subtraction/sub old mode 100644 new mode 100755 index e69de29..72d9a44 --- a/subtraction/sub +++ b/subtraction/sub @@ -0,0 +1,119 @@ +#!/bin/sh +# long subtraction !? +# $f1 - $f2 +countd() { # count decimal places + m="$1"; n=${2:-0}; while [ "$m" ]; do + : $((n+=1)) + next="${m%?}" + [ "${m#$next}" = "." ] && { + break + } || { + m="$next" + } + done + echo "$n" +} +borrow(){ + # $2 current number (to increase) + # $1 as whole number; will return modified + # $3 as $next + b="${1%$2}"; b="${b#${3%?}}" + [ "$b" -gt 0 ] && { + c1="$2"; + [ "$b" -eq 10 ] && { + o="${1%$b$2}"; : $((b-=1)); o="${o}0${b}$c1" # eg 21 = 2090 10 + # tbh idk why this works; 2090 should acctually be 1 10 9 10 + # which somehow becomes 209 10 ? I'm guessing a second borrow call is made + # and that somehow corrects it; but again idk; a second borrow call /is/ made + # but idk how it corrects it + } || { + o="${1%$b$2}"; : $((b-=1)); o="$o$b$c1" + } + : $((c1+=10)) + echo "$o $c1" + } || { # otherwise use recusion + o="${1#${3%?}}"; o="${o%$2}" + borrow "$1" "$o" "${3%?}" + } +} +[ -z "${1##*.*}" -o -z "${2##*.*}" ] && { + + if [ ! -z "${1##*.*}" ]; then # if $1 is not float + zp1="$1"; zp2="${2%.*}${2#*.}" + elif [ ! -z "${2##*.*}" ]; then + zp1="${1%.*}${1#*.}"; zp2="$2" + else + zp1="${1%.*}${1#*.}"; zp2="${2%.*}${2#*.}" + fi # yank out decimal places to compare + if [ "${#zp1}" -gt "${#zp2}" ]; then + until [ "${#zp2}" -eq "${#zp1}" ]; do + zp2="${zp2}0" + done + elif [ "${#zp1}" -lt "${#zp2}" ]; then + until [ "${#zp1}" -eq "${#zp2}" ]; do + zp1="${zp1}0" + done + fi + [ "$zp2" -gt "$zp1" ] && { + set -- "$2" "$1" + nr=- + } + # above handles negative results + + # determine decimal point + if [ "${#1}" -gt "${#2}" -a -z "${1##*.*}" ]; then # if $1 has no decimal points it should not be counted + # this fixes a but when $1 is longer than $2 but has no decimal points + dn=$(countd "$1") + elif [ "${#1}" -lt "${#2}" -a -z "${2##*.*}" ]; then # same here + dn=$(countd "$2") + else # equal + dn=$(countd "$2") + fi + zp1="${1%%.*}"; zp2="${2%%.*}" + [ "${#zp1}" -gt "${#zp2}" ] && until [ "${#zp1}" -eq "${#zp2}" ]; do + set -- "$1" "0$2" + zp1="${1%%.*}"; zp2="${2%%.*}" + done + [ "${#zp1}" -lt "${#zp2}" ] && until [ "${#zp1}" -eq "${#zp2}" ]; do + set -- "0$1" "$2" + zp1="${1%%.*}"; zp2="${2%%.*}" + done; unset zp1 zp2 + [ "$dn" -gt 0 ] && : $((dn-=1)) + if [ ! -z "${1##*.*}" ]; then # if $1 not float + set -- "${1}.0" "$2" + elif [ ! -z "${2##*.*}" ]; then + set -- "$1" "${2}.0" + fi + #echo "$1 $2" + set -- "${1%.*}${1#*.}" "${2%.*}${2#*.}" # remove decimals + f1="$1"; f2="$2" + [ "${#f1}" -lt "${#f2}" ] && until [ "${#f1}" -eq "${#f2}" ]; do + f1="${f1}0" + done + [ "${#f1}" -gt "${#f2}" ] && until [ "${#f2}" -eq "${#f1}" ]; do + f2="${f2}0" + done # 0 padding + #echo "$f1 - $f2" + while [ "$f1" ]; do + while [ "$f2" ]; do # shift over both numbers; double while + next1="${f1%?}"; next2="${f2%?}"; c1="${f1#$next1}"; c2="${f2#$next2}" + [ "$c1" -lt "$c2" ] && { # regroup + b=$(borrow "$f1" "$c1" "$next1") + c1="${b#* }"; f1="${b% *}"; next1="${f1%?}" + #echo "-- $f1 / $b" + } + #echo "$c1 - $c2 | $f1 - $f2" + o="$((c1-c2))$o" # subtract + f1="$next1"; f2="$next2" + done + done + [ "$dn" -gt 0 ] && { + n=0; f1="$o"; while [ "$f1" ]; do + next="${f1%?}" + : $((n+=1)) + [ "$n" -eq "$dn" ] && o="$next.${o#${f1%?}}" + f1="$next" + done + } + echo "${nr}$o" # $nr is for negative handling +} || echo $(($1-$2)) # NOT float