Unix bc command and its l flag
In a recent article about Unix utilities, I
wrote:
We need the
l flag on bc
because otherwise it stupidly does integer arithmetic.
This is wrong, as was kindly pointed out to me by Luke Shumaker. The
behavior of bc is rather more complicated than I said, and less
stupid. In the application I was discussing, the input was a string
like 0.25+0.37 , and it's easy to verify that bc produces the
correct answer even without l :
$ echo 0.25+0.37  bc
.62
In bc , each number is
represented internally as !!m·10^{s}!!, where !!m!! is in base 10 and
!!s!! is called the “scale”, essentially the number of digits after
the decimal point. For addition, subtraction, and multiplication, bc
produces a result with the correct scale for an exact result. For
example, when multiplying two numbers with scales a and b, the
result always has scale a + b, so the operation is performed with
exact precision.
But for division, bc doesn't know what scale it should use for the
result. The result of !!23÷7!! can't
be represented exactly, regardless of the scale used. So how should
bc choose how many digits to retain? It can't retain all of them,
and it doesn't know how many you
will want. The answer is: you tell it, by setting a special variable,
called scale . If you set scale=3 then !!23÷7!! will produce the
result !!3.285!!.
Unfortunately, if you don't set it — this is the stupid part — scale defaults to zero. Then
bc will discard everything after the decimal point, and tell you that
!!23÷7 = 3!!.
Long, long ago I was in the habit of manually entering scale=20 at
the start of every bc session. I eventually learned about l ,
which, among other things, sets the default scale to 20 instead of 0.
And I have used l habitually ever since, even in cases like this,
where it isn't needed.
Many thanks to Luke Shumaker for pointing this out. M. Shumaker adds:
I think the misrecollection/understanding of l says something
about your "memorized trivia" point, but I'm not quite sure what.
Yeah, same.
[Other articles in category /oops]
permanent link
