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, and note that non-Bash printf need not support %f and %g).
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:
# 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
}
(Note - this function is written in portable (POSIX) shell, but assumes that printf handles the floating-point conversions. Bash has a built-in printf that does, so you're okay here, and the GNU implementation also works, so most GNU/Linux systems can safely use Dash).
Test cases
radix=$(printf %.1f 0)
for i in $(seq 12 | sed -e 's/.*/dc -e "12k 1.234 10 & 6 -^*p"/e' -e "y/_._/$radix/")
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 these 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.