This answer to the first linked question has the almost-throwaway line at the end:
See also
%gfor rounding to a specified number of significant digits.
So you can simply write
printf "%.2g" "$n"
(but see the section below on decimal separator and locale)
Examples:
$ printf "%.2g\n" 76543 0.0076543
7.7e+04
0.0077
Of course, you now have mantissa-exponent representation rather than pure decimal, so you'll want to convert back:
$ printf "%0.f\n" 7.7e+06
7700000
$ printf "%0.7f\n" 7.7e-06
0.0000077
Putting all this together, and wrapping it in a function:
#!/bin/sh
# Function round(precision, number)
round() {
n=$(printf "%.${1}g" "$2")
if [ "$n" != "${n#*e}" ]
then
f="${n##*e-}"
test "$n" = "$f" && f= || f=$(( ${f#0}+$1-1 ))
printf "%0.${f}f" "$n"
else
printf "%s" "$n"
fi
}
Test cases
for i in $(seq 12 | sed -e 's/.*/dc -e "12k 1.234 10 & 6 -^*p"/e')
do
echo $i "->" $(round 2 $i)
done
Test results
.000012340000 -> 0.000012
.000123400000 -> 0.00012
.001234000000 -> 0.0012
.012340000000 -> 0.012
.123400000000 -> 0.12
1.234 -> 1.2
12.340 -> 12
123.400 -> 120
1234.000 -> 1200
12340.000 -> 12000
123400.000 -> 120000
1234000.000 -> 1200000
A note on decimal separator and locale
All the working above assumes that the radix character (also known as the decimal separator) is ., as in most English locales. Other locales use , instead, and some shells have a built-in printf that respects locale. In this shells, you may need to set LC_NUMERIC=C to force the use of . as radix character, or write /usr/bin/printf to prevent use of the built-in version. This latter is complicated by the fact that (at least some versions) seem to always parse arguments using ., but print using the current locale settings.