How do I get bc
to start decimal fractions with a leading zero?
$ bc <<< 'scale=4; 1/3'
.3333
I want 0.3333.
How do I get bc
to start decimal fractions with a leading zero?
$ bc <<< 'scale=4; 1/3'
.3333
I want 0.3333.
bc
natively does not support adding zero.
Workaround is:
echo 'scale=4; 1/3' | bc -l | awk '{printf "%.4f\n", $0}'
0.3333
\n
– terminate the output with a newline.
%f
– floating point
%.4f
– the number of digits to show.
This specifies 4 digits after the decimal point.
bc
, just echo 1 3 4 | awk '{ printf ("%.*f\n", $3, $1 / $2); }'
. But gawk has BigNum compiled in anyway (on most distros).
– Paul_Pedant
Mar 02 '23 at 10:37
-l
(math library) option to bc
, your answer doesn’t need it either.
– G-Man Says 'Reinstate Monica'
Apr 12 '23 at 02:54
Unfortunately bc
is written in such a way that you cannot. This statement also applies to its neighbor dc
. People, as a solution, usually suggest using some text-processing tool to change bc
output, or use completely different tool like perl
or python
which has different syntax, but to me they seems to be too heavy for such simple task.
From your other questions it looks that you are zsh
user so I would suggest zcalc
, which has very similar syntax for basic operations like bc
:
$ zcalc -e '1/3'
0.333333
First you need to load this function (e.g. inside .zshrc
) and probably you may want to always treat all numbers as a floating point with -f
option:
autoload -U zcalc
alias zcalc='zcalc -f'
As a bonus, you can define special prompt for the calculator with ZCALCPROMPT
parameter, for details look at man zshcontrib
.
bc
can be persuaded to use a leading zero:
for div in 10 1000; do
echo "scale=3;v=158/$div; if(v > -1 && v < 1) print 0,v,\"\n\" else print v, \"\n\"" | bc
done
v > -1
, but that doesn't work for negative numbers as you insert the 0
before the sign (and get something like 0-.158
instead of -0.158
).
– Stéphane Chazelas
Apr 09 '23 at 13:44
00
.
– G-Man Says 'Reinstate Monica'
Apr 10 '23 at 02:31
No need for awk
if you have printf
(either builtin to the shell, or as a separate program).
If you specifically want four digits to the right of the decimal point,
$ printf '%.4f\n' "$(bc <<< 'scale=4; 1/7')"
0.1428
If you want to make it scriptable,
$ ndigits=4
$ printf '%.*f\n' "$ndigits" "$(bc <<< "scale=$ndigits; 1/7")"
0.1428
If you want to suppress trailing zeroes, use %g
instead of %f
.
$ printf '%.4g\n' "$(bc <<< 'scale=4; 1/3')" \
"$(bc <<< 'scale=4; 1/4')" \
"$(bc <<< 'scale=4; 1/7')" \
"$(bc <<< 'scale=4; 1/8')"
0.3333
0.25
0.1428
0.125
But this works the way you want only if the value is between −1 and 1:
$ printf '%.4g\n' "$(bc <<< 'scale=4; 1/7')" \
"$(bc <<< 'scale=4; 10/7')" \
"$(bc <<< 'scale=4; 100/7')" \
"$(bc <<< 'scale=4; 1000/7')"
0.1428
1.429
14.29
142.9
because the 4
here is interpreted as the total number of digits,
not the number of digits to the right of the decimal point.
printf
implementations, that won't work if the locale decimal radix character is the comma instead of period as printf
honours is but bc
doesn't.
– Stéphane Chazelas
Apr 10 '23 at 06:18
This is a belt-and-braces solution that addresses the failures using my previous answer. This small function somewhat intelligently figures out when and where to stick the leading 0 and negative sign and uses the backspace
control-code to move backwards in the printed value. It won't work in Posix -s|--standard
mode (or if printed on a Teletype!):
#!/usr/bin/env bc
# this is lz.bc
define lz(d) {
if (ibase != 10 || obase != 10) {
print "(io)base must be decimal (10)\n"
return -1
}
n=0; b=0; a=0
if (d<0) n=1 # negative
if (d>-1 && d<0) b=1 # below
if (d>0 && d<1) a=1 # above
print " ", d
for (i=length(d)+1; i>=0; i--) {
print "\b"
if(i==0 && (b || a)) print "0\b\b"
}
if(n) print "-"
print "\n"
return 0
}
v[0]=-.234
v[1]=.234
v[2]=-2.345
v[3]=2.345
v[4]=-123.4567
v[5]=123.456
for(x=0;x<6;x++) {
print v[x], " ... "
r=lz(v[x])
}
obase=16
r=lz(v[5])
quit
which when called displays:
$ bc lz.bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
-.234 ... -0.234
.234 ... 0.234
-2.345 ... -2.345
2.345 ... 2.345
-123.4567 ... -123.4567
123.456 ... 123.456
(io)base must be decimal (10)