Thank you for posting that, I enjoy playing with shell scripts for odd purposes.
Unfortunately, my knowledge of
bc(1) is about zero, so naturally the first thing that came to my mind after looking at your script was "
Hmmm, could you do that just with shell arithmetic and without bc ?" At first I thought it would be problematic, but after thinking about it a bit it seemed it would not be that difficult. So I had some fun writing a script to do it (shown below).
Here is my "analysis" which also explains how the script works. The script takes 3 arguments,
$1 = A = whole number of inches
$2 = B = numerator of fractional part
$3 = C = denominator of fractional part
So, "A B C" means A+B/C inches, which will be converted to cm with 4 digits precision, as an example. A and B must be non-negative integers, and C a positive integer. Then
( A + B/C ) inch = N * 10^{-4} cm
where N is a non-negative integer that we seek to find. A little algebra gives
[ ( AC + B) / C ] * 10^4 inch = N cm
Using inch = 2.54 cm this gives an answer for N:
N = [ ( AC + B ) / C ] * 10^2 * 254 = [ ( AC + B ) * 25400 ] / C
But, shell arithmetic is going to truncate this division, so to round it I think we should add C/2 to the top. I.e., if X is the [...] then replace it wtih X+C/2 = (2X+C)/2. Then the rounded value for N is
N = [ ( AC + B ) * 25400 * 2 + C ] / (2C)
Finally we want the integer and fractional parts of N * 10^{-4}. These are:
I = floor( N / 10^4 )
and (remainder times 10^4):
R = ( N - I * 10*4 )
The answer is basically "I.R" printed properly with printf().
Code:
#!/bin/sh
# Inches to CentiMeters (to 4 decimal precision)
# Arguments: $1 = whole inches; $2 = fractional numerator; $3 = fractional denominator
# i.e., $1 + $2 / $3 [inches]
# Both $2 and $3 can be omitted together (for a whole inch)
# Argument checking is a bit rudimentary ...
if [ $# -eq 0 -o $# -eq 2 -o $# -ge 4 ]; then
echo Error a.
exit
fi
A=$1
B=${2:-0}
C=${3:-1}
if [ $C -le 0 ]; then
echo Error b.
exit
fi
N=$(( ( A * C + B ) * 25400 * 2 + C ))
N=$(( N / ( 2 * C ) ))
I=$(( N / 10000 ))
R=$(( N - I * 10000 ))
printf ">> %d + %d / %d in = %d.%04d cm\n" $A $B $C $I $R
(To convert a whole number of inches, the script allows a single argument.)
Comments and corrections are welcome, as I haven't checked this extensively, but it seems to work in several cases I tried.
EDIT: There's a bug in the attached file. The printf statement should contain
%04d as shown in the code block. Ooops. Hmmm, it seems the file didn't attach, just as well I guess! You can copy from the code block.