I am writing a simple bash script to calculate a square root to 3 decimal places by default but the user can set the number of places... Nothing complex, I just iterate from 1 to the lowest square root. Since my bash is still basic this is what I came up with.
#!/usr/bin/env bash
num=${1}
places=${2-3}
i=0
while [[ $(( i*i )) -lt ${num} ]] // <= The problem should be here
do
i=$(( i + 1 ))
done
echo ${i};
rem=$(( num % i ))
root="${i}."
for (( j=0; j<places; j++ ))
do
rem=$((rem * 10))
root="$root$((rem / i))"
rem=$((rem % i))
done
echo ${root}
But due to some reason, it won't produce the correct result for a wide range of numbers
like bashfile.sh 9 // will produce 3.000 but bashfile.sh 8 will return 3.666
kindly help, what is wrong with while [[ ]]
Here is a fairly simple, although not very efficient solution:
#!/bin/bash
num=$1
prec=${2:-3}
for (( i=0; i < prec; ++i )); do let num*=100; done
for (( sqrt=0; sqrt*sqrt <= num; ++sqrt )); do :; done
let --sqrt
sqrt="${sqrt:0:-prec}.${sqrt: -prec}"
echo $sqrt
To answer your question ("what is wrong with while [[ ]]
"), your comparison was slightly incorrect. Instead of -lt
(ie, <
) it should have been <=
. And you needed to subtract 1 from i
after the loop to get the correct whole part of the square root.
I couldn't make sense of the second part of your code that calculates decimal places. However, a simple solution is to instead pre-multiply the original number to get needed precision, which is what I've done above.
UPDATE
As @dash-o has pointed out if you are using bash, chances are you have either bc or awk installed, which are better suited for this:
num=$1
prec=${2:-3}
# using bc
echo "scale=$prec; sqrt($num)" | bc
# using awk
awk "BEGIN {printf \"%.${prec}f\n\", sqrt($num)}"