psh-fractional/division/div
2022-02-24 12:57:33 -05:00

115 lines
2.8 KiB
Bash
Executable file

#!/bin/sh
s() {
n=$1; i=1; while [ "$n" -le $2 ]; do
echo "$n"; : $((n+=i))
done
} # seq
fd() { # return first digit of $1
x="$1"; until [ "${#x}" -eq 1 ]; do
x="${x%?}"
done
echo "$x"
}
countd() { # count decimal places
m="$1"; n=${2:-0}; while [ "$m" ]; do
: $((n+=1))
next="${m%?}"
[ "${m#$next}" = "." ] && {
break
} || {
m="$next"
}
done
echo "$n"
}
ld() { # $1/$2
if [ ! -z "${1##*.*}" -a -z "${2##*.*}" ]; then
di="${1}."; until [ "${#di}" -eq "$((${#2}+1))" ]; do
di="${di}0"
done
set -- "$di" "$2" "$3"
elif [ ! -z "${2##*.*}" -a -z "${1##*.*}" ]; then
div="${2}."; until [ "${#div}" -eq "$((${#1}+1))" ]; do
div="${div}0"
done
set -- "$1" "$div" "$3"
fi
[ -z "${1##*.*}" -o -z "${2##*.*}" ] || {
set -- "$1.00" "$2.00" "$3"
}
di="${1##*.}"; div="${2##*.}"
until [ "${#di}" -ge "${#div}" ]; do
di="${di}0"
done
until [ "${#div}" -ge "${#di}" ]; do
div="${div}0"
done
set -- "${1%%.*}.$di" "${2%%.*}.$div" "$3"
# handle decimal less numbers
#echo "$1/$2"
di="$1"; div="$2"; count="$3"
case "$div" in
*'.'*) # if $2 has a decimal we must shift
set -- "${1%.*}${1#*.}" "${2%.*}${2#*.}" "$3" # shift $2 # simply remove the decimal point
until [ "${#1}" -ge "${#2}" ]; do
set -- "${1}0" "$2" "$3"
done
set -- "$1.00" "$2" "$3" # add decimals back in for $1 only
esac
#echo "$1 $2"
di="$1"; div="$2"; count="$3" # redeclare
#echo "$sp $div ${di}/${#di} | $1/$2 | $di/$div"
o="$((${di%.*}/${div%.*}))"; [ "${#o}" -eq 0 ] && : $((count+=2)); : $((count+=${#o}))
sd="${di%.*}"; : $((count+=${#sd}));
until [ "${#di}" -eq "$((count+1))" ]; do
di="${di}0"
done
: $((count-=1)) && di="${di%0}"
set -- "$1" "$2" "${3:-9}" "$di"
unset IFS o; n=0; for i in $(s 1 $count); do
fd="$(fd $di)" # fd is needed later
[ "$fd" = '.' ] && {
dp="$n"
di="${di#?}"; fd="$(fd $di)"
}
[ "$i" -gt 1 ] && {
fd="${sd}${fd}"
#echo "$fd"
}
sd="$((fd/div))"; [ "$sd" -eq 0 ] && : $((count+=1))
o="${o}${sd}"; sd="$((sd*div))"
#printf " %s\n- %s\n" "$fd" "$sd"
sd="$((fd-sd))"
#echo "| $sd -- $i"
di="${di#?}" # $fd$sd
: $((n+=1))
done
n=0; sd="$o"; while [ "$sd" ]; do
next="${sd#?}"
[ "$n" -eq "$dp" ] && {
o="${o%$sd}.$sd"
break
}
sd="$next"
: $((n+=1))
done
until [ "${o#0}" = "$o" ]; do
o="${o#0}"
done
#echo "$o"
if [ ! -z "${o##*.*}" -a "$dp" -gt 0 ]; then # missing decimal place
do="$o"; [ "${#do}" -gt "$dp" ] && until [ "${#do}" -eq "$dp" ]; do
do="${do%?}"
done
o="${do:-0}.${o#$do}"
fi
[ "$(fd $o)" = '.' ] && o="0$o"
echo "$o" # | $1/$2 | $dp | $do || $fd $1"
}
# 9 decimal points unless $3 is passed
[ "$1" -a "$2" ] && ld "$1" "$2" "${3:-9}"