If like me, you do most of your work from the command-line,
using vim to edit files, mutt for e-mails, cd/ls/mv/find/etc instead
of a file manager, then you may get annoyed by having to fire up
a GUI calculator to make (what may sometimes be) a single calculation.
One useful feature of calculating on the command-line is that
you can see what you've typed. For instance, sometimes when I'm entering
a long, complex calculation on a calculator (either the GUI or the solid,
hold-in-your-hand type), I sometimes forget if I've actually typed
in all those numbers or made the calculations in the right order.
Maybe it's just me ...
This article shows how to quickly perform standard calculations
on the command line including
addition, subtraction, multiplication, division, square root,
powers, conversion from decimal to hex, decimal to binary, hex to
decimal, and binary to decimal. It also briefly introduces using
bc in interactive mode and how to write files for
use with bc for frequently repeated operations.
There is a mention of using Google for performing calulations.
It finishes with a little challenge to test the power of your CPU.
Other advantages of using bc include:
bc is included with (almost?) all Linux distros as standard, as well as (again, almost?) all Unices.
- Results from calculations in some proprietary flavours of
bc have up to 99 decimal digits before and after the decimal point. This limit has been greatly surpassed in GNU bc. I don't know what that limit is, but it's at least many, many tens of thousands. Certainly it's more than any GUI-based calculators (I've used) could accomodate.
- You may also find yourself working in an environment where you simply don't have access to a GUI.
- The syntax for basic sums is almost identical to Google's calculator function, so you can learn how to use two utilities in one go!
bc is a preprocessor for dc.
The useful thing about bc is that it accepts
input from files and from standard input. This allows us
to pipe data to it for quick calculations.
Most of these examples follow a simple formula.
addition
$ echo '57+43' | bc
100
subtraction
$ echo '57-43' | bc
14
multiplication
$ echo '57*43' | bc
2451
scale
The scale variable determines the number of digits which
follow the decimal point in your result.
By default, the value of the scale variable is zero.
(Unless you use the -l option in which case it defaults
to 20 decimal places. More about -l later.)
This can be set by declaring scale before your calculation,
as in the following division example:
division
$ echo 'scale=25;57/43' | bc
1.3255813953488372093023255
square root
$ echo 'scale=30;sqrt(2)' | bc
1.414213562373095048801688724209
This beats Google's calculator function which only calculates the result to 8 decimal places!
Although Google's calculator function has this 8 decimal places limitation, it will allow imaginary numbers as answers.
power
$ echo '6^6' | bc
46656
parentheses
If you have read
Robert Heinlein's The Number of the Beast,
you may recall that the number of parallel universes
in the story equals (six to the power of six) to the power of six.
If you should try to calculate that like this:
$ echo '6^6^6' | bc
You will get a screen full of numbers (some 37374 digits), not the
10314424798490535546171949056
that you might expect.
If you're running a non-GNU version of bc,
you'll most likely get something like:
exp too big
empty stack
save:args
The Google Calculator balks at '6^6^6' as well. Good ol' GNU.
That's because you typed the wrong question. You need to type:
$ echo '(6^6)^6' | bc
Whereas what you did type was interpreted as:
$ echo '6^(6^6)' | bc
which is an entirely different number altogether. So the positioning of
parentheses (brackets to you and me!) is very important.
I use brackets to separate the different components of my sums
whenever possible, just eliminate any possible doubt that I may get the
wrong answer.
Consider the following calculations:
$ echo '7+(6*5)' | bc
$ echo '7+6*5' | bc
$ echo '6*5+7' | bc
They all give the same answer, 37, but I would have typed the first
calculation, unless of course, I meant:
$ echo '(7+6)*5' | bc
Or to put it another way:
$ echo '13*5' | bc
which is 65.
obase and ibase
obase and ibase are special variables
which define output and input base.
Legitimate obase values range from 2 to 999, although anything beyond 16 is wasted on me!
Legitimate ibase values range from 2 to 16.
Some examples will explain all this better.
convert from decimal to hexadecimal
Here we're converting 255 from base 10 to base 16:
$ echo 'obase=16;255' | bc
FF
convert from decimal to binary
And here we're converting the number 12 from base 10 to base 2:
$ echo 'obase=2;12' | bc
1100
Which reminds me of the old joke:
There are only 10 types of people in the world -- those who understand binary, and those who don't.
Which leads us neatly onto the next example:
convert from binary to decimal
Here we're converting the binary number 10 to a base 10 (decimal) number.
$ echo 'ibase=2;obase=A;10' | bc
2
Note that the obase is "A" and not
"10". Sorry, you've got to learn some hex. The reason
for this is you've set the ibase to "2",
so if you now had tried to use "10" as the value for the
obase, it would stay as "2", because
"10" in base 2 is "2". So you need to use hex
to "break out" of binary mode.
Well, that was just to explain the joke; now something a bit more challenging:
$ echo 'ibase=2;obase=A;10000001' | bc
129
convert from hexadecimal to decimal
$ echo 'ibase=16;obase=A;FF' | bc
255
Again, note the use of "A" to denote base 10. That is
because "10" in hex (base 16 - the ibase value)
is 16.
a brief introduction to interactive mode
You can also run bc in interactive mode:
$ bc
If you're running GNU bc, you should get the following notice:
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
Followed by an uninviting blank prompt.
Otherwise you'll just get an uninviting blank prompt.
If you wish to get straight to the uninviting blank prompt, use the
-q option, which runs bc in quiet mode,
preventing the normal GNU bc welcome from being printed:
$ bc -q
Using the basics we've been through from the examples
above, enter a calculation:
scale=5
57/43
1.32558
Type quit to exit bc interactive mode.
using bc with shell scripts
You can use shell variables with bc,
which is very useful in shell scripts:
$ FIVE=5 ; echo "$FIVE^2" | bc
25
Note the use of double-quotes to preserve the value of
the variable $FIVE.
a brief introduction to using bc with files
Using bc with files allows complex calculations to be
repeated, again and again, a bit like using a spreadsheet to
run the same calculations on changing figures ... but faster.
Here is a simple example:
scale=2
/* C-style comments
are allowed, as are spaces */
print "\nConvert Fahrenheit to Celsius\n\n"
print "Temperature in Fahrenheit: " ; fah = read()
print "\n"
print "Equivalent Temperature in Celsius is: "
(fah - 32.0) * 5.0 / 9.0
quit
Create and save the file, then run it like this:
$ bc -q filename
Convert Fahrenheit to Celsius
Temperature in Fahrenheit: 61
Equivalent Temperature in Celsius is: 16.11
Note that this example has only been tested with GNU bc.
Other (proprietary) versions of bc may have more stringent
syntax requirements. Some bcs don't allow the use of
print or read, for example,
so you have to edit your file before each calculation. Not very useful.
a quick challenge for your PC (GNU bc only)
If you wish to test the comparative speed of your PC, try this
challenge: use bc to calculate Pi to 5000 decimal places.
The idea for this challenge came from a great
article at Geekronomicon.
If you really want to tie up your machine for an hour (or more), you
could try the "Pi to 25000 decimal places" challenge from the aforementioned
Geekronomicon.
First, to put things in perspective, here is some information about my CPU:
$ cat /proc/cpuinfo | egrep "model name|MHz"
model name : AMD Athlon(tm) 64 Processor 3500+
cpu MHz : 2211.346
Note the use (below) of the command bc -l -q.
-l
loads the math library which is required for the use of the
"a" (arctangent) in the calculation for Pi.
You can learn more about the math library functions in the
bc command manual.
I'm not sure what effect the -q option
(quiet, no welcome message printed)
has on our test, but I guess it can't harm.
$ time echo "scale=5000; 4*a(1)" | bc -l -q
3.141592653589793238462643383279502884197169399375105820974944592307\
...
...
...
73774418426312986080998886874132604720
real 0m44.164s
user 0m44.099s
sys 0m0.008s
44.099 seconds! Not bad.
I imagine that some Gentoo folks
may be interested to see what difference their compile-time
optimisations make to the speed of bc.
FWIW, my distro of choice is
Arch Linux.
useful links
GNU bc manual
Google's calculator function
Monday, November 27. 2006 at 11:43 (Reply)
also, how prevalent is python becoming because i find it a lot easier to use than bc, especially with all the other easy-to-import modules.
Monday, November 27. 2006 at 12:02 (Link) (Reply)
Monday, November 27. 2006 at 11:57 (Reply)
real 0m41.555s
user 0m41.275s
sys 0m0.152s
Monday, November 27. 2006 at 12:18 (Link) (Reply)
Can someone out here tell me how to stream calculations through bc ?
e.g.: I want to compute to amount of space needed to copy all Java source files located in /home/me/src ?
bash# find /path -type f -iname '*.txt' -ls | gawk '{print $7 }' | .... | bc
What should the dots look like ?
Thank you,
Benoît
Monday, November 27. 2006 at 12:30 (Link) (Reply)
There is no requirement for bc. You could use something like:
find /path -type f -iname '*.txt' -ls | gawk '{ s += $7 } END { print s }'
Regards,
Rob
Monday, November 27. 2006 at 13:14 (Reply)
$ find /path -type f -iname '*.txt' -ls | gawk '{sum+=$7}END{print sum}'
Monday, November 27. 2006 at 12:31 (Reply)
Thank you very much!
Monday, November 27. 2006 at 14:41 (Link) (Reply)
Monday, November 27. 2006 at 15:05 (Link) (Reply)
Oops.
Regards,
Rob
Tuesday, November 28. 2006 at 03:53 (Reply)
it does compute the value of Pi but converges pretty slowly. for example, after calculating the 5th term of the series, the approximation is around 3.339
using the same method but replacing x=1/sqrt( 3 ) instead gets quicker near the value of Pi. after the 5th term of the series, the approximation of Pi is 3.14260
reference: http://www.ams.org/featurecolumn/archive/pi-calc.html
Monday, November 27. 2006 at 17:12 (Reply)
Monday, November 27. 2006 at 20:48 (Reply)
(OS X 10.4.
Monday, November 27. 2006 at 18:22 (Reply)
real 1m8.500s
user 1m8.302s
sys 0m0.084s
Sunday, December 10. 2006 at 10:19 (Reply)
model name : Intel(R) Pentium(R) M processor 1700MHz
cpu MHz : 1700.000
Monday, November 27. 2006 at 18:46 (Reply)
01010101 bin is 55 hex.
However when I type echo 'ibase=2;obase=F;01010101' | bc the answer comes back 5A hex.
What is going on? I tried it on Debian Linux, NetBSD and OpenBSD. Must be operator error, should obase be set to something else?
Monday, November 27. 2006 at 19:43 (Link) (Reply)
echo 'ibase=2;obase=F;01010101' | bc
you're using decimal 15 (hex F) as output base.
0x55 = 5*16+5 = 85
(dec) = 5*15+10 = 5A (base 15)
Try to express obase in binary:
echo 'ibase=2;obase=10000;01010101' | bc
Wednesday, November 29. 2006 at 01:34 (Reply)
i.e)
echo 'obase=16;ibase=2;01010101' | bc
no tricky at all
Monday, November 27. 2006 at 18:55 (Link) (Reply)
real 4m10.032s
user 2m38.012s
sys 0m1.403s
omg...gotta get a new laptop...
Monday, November 27. 2006 at 21:22 (Reply)
On my 1.5GHz PowerBook G4; OS X 10.4.8:
real 1m36.602s
user 1m19.415s
sys 0m1.057s
The G4s also seem to be a little faster than the G5s for some reason.
Monday, November 27. 2006 at 18:58 (Reply)
OS/X version 10.4.8
real 1m29.076s
user 1m27.758s
sys 0m0.570s
Monday, November 27. 2006 at 19:21 (Link) (Reply)
GP/PARI CALCULATOR Version 2.1.6
(which is my favourite calculator)
(20:17) gp > \p 5000
realprecision = 5009 significant digits (5000 digits displayed)
(20:17) gp > 4*atan(1.)
time = 24 ms.
%1 = 3.141592653589793238462643[...]
Monday, November 27. 2006 at 19:45 (Reply)
obase=F is setting the output base to 15
echo 'ibase=2;obase=10000;01010101' | bc
55
echo 'obase=16;ibase=2;01010101' | bc
55
Monday, November 27. 2006 at 21:15 (Link) (Reply)
cpu MHz : 2000.082
real 0m58.122s
user 0m57.960s
sys 0m0.068s
Not bad for a $50 cpu
Monday, November 27. 2006 at 21:46 (Reply)
real 2m47.996s
user 2m37.566s
sys 0m0.084s
~2x your G5, but ~10x older
Tuesday, November 28. 2006 at 01:13 (Reply)
Intel(R) Pentium(R) M processor 1.60GHz (1601 BogoMips)
real 1m5.593s
user 1m4.892s
sys 0m0.008s
Using Debian Testing with a locally compiled 2.6.15 (preempt) kernel.
Tuesday, November 28. 2006 at 03:14 (Reply)
real 0m55.205s
user 0m55.013s
sys 0m0.103s
Not very fast!
Tuesday, November 28. 2006 at 09:04 (Link) (Reply)
Tuesday, November 28. 2006 at 10:41 (Reply)
cat /proc/cpuinfo | egrep "model name|MHz"
model name : Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
cpu MHz : 2394.062
model name : Intel(R) Core(TM)2 CPU 6600 @ 2.40GHz
cpu MHz : 2394.062
real 0m35.305s
user 0m35.178s
sys 0m0.108s
Of course, it only used one CPU so I got on with some work while it was running.
I generally use dc rather than bc as I've always preferred Reverse Polish notation.
Tuesday, November 28. 2006 at 10:46 (Reply)
(gdb) p 3.0/8
$1 = 0.375
(gdb) p $1*(5-9)
$2 = -1.5
(gdb) p/x 255
$3 = 0xff
(gdb) p/c 35
$4 = 35 '#'
(gdb) help p
(gdb) help x
Tuesday, November 28. 2006 at 12:14 (Reply)
in you .bash_profile, just put
calc(){ perl -wlne'print eval'; }
export -f calc
and use calc from the command line (exit with Ctrl-C)
Alessandro
Tuesday, November 28. 2006 at 16:25 (Link) (Reply)
However, if you find yourself using it often you should try calc (http://www.isthe.com/chongo/tech/comp/calc/) instead as it is a bit nicer.
If you like the RPN style calculators (like HP) then you should try Orpie (http://www.eecs.umich.edu/~pelzlpj/orpie/)
Wednesday, November 29. 2006 at 00:39 (Reply)
echo $((4+5))
"let" is also nice, ignorant as I am I only use it for shell-loops sometimes:
i=4
for foo in bar; do something with foo; let i+=2; done
But bc is indeed a nice tool, I'm doing my cryptography homework with it.
cu,
pepe
Wednesday, November 29. 2006 at 06:42 (Reply)
http://sial.org/howto/shell/useless-cat/
so instead of
cat /proc/cpuinfo | egrep "model name|MHz"
one might just use
egrep "model name|MHz" < /proc/cpuinfo
Wednesday, November 29. 2006 at 11:27 (Reply)
In the same vein, useless use of shell redirection spotted. Use the grep/egrep file parameter, thus avoiding redirection:
egrep "model name|MHz" /proc/cpuinfo
BTW:
model name : AMD Opteron(tm) Processor 242
cpu MHz : 1589.818
model name : AMD Opteron(tm) Processor 242
cpu MHz : 1589.818
So dual Opteron, 1.6 GHz, but bc appears to be single threaded, so only one CPU is used, but my streaming hurricanefm.com kaffeine session w/ goom visualization running mostly on the other CPU continued uninterrupted. (It and other system processes are using ~10% on the CPU bc used, thus the realtime/usertime discrepancy). Gentoo/amd64, vanilla 2.6.19-rc5 kernel, glibc 2.4-r4 (2.5 seems to have SMP? memory ops handling issues that cause crashes in various a/v apps such as kaffeine and xmms), gcc 4.1.1-r2.
real 1m32.591s
user 1m22.830s
sys 0m0.110s
I'll be upgrading to dual-core 2.6 GHz Opti 285s soon -- street prices are down to ~$1200 for the pair. Looking forward to the four-way processing AND the MHz boost. =8^)
Very useful article -- bookmarked! I'd discovered bc based on a chance comment I read somewhere, but hadn't used it a lot and hadn't discovered the scale or i/obase options, so found it rather limited, particularly for division. This helps greatly! I'm also a fan of RPN, so now have dc to explore. =8^)
Wednesday, November 29. 2006 at 12:00 (Reply)
You guys are comparing apples and screwdrivers.
Thursday, November 30. 2006 at 01:56 (Reply)
Friday, December 1. 2006 at 20:08 (Link) (Reply)
.......
real 1m14.555s
user 1m13.407s
sys 0m0.157s
....
In Maple 10, less than one second.
Sunday, December 3. 2006 at 07:37 (Reply)
user 0m31.098s
sys 0m0.008s
model name : Intel(R) Xeon(R) CPU 5150 @ 2.66GHz
cpu MHz : 2666.838
from work server with minimal load (HP DL380g5, 2x dual core, 8GB ram, 4 x 147gb sas in RAID5)
Wednesday, December 6. 2006 at 20:05 (Reply)
real 1m27.282s
user 1m26.795s
sys 0m0.046s
Sunday, December 10. 2006 at 08:21 (Reply)
FIVE=5 ; echo "$FIVE^2" | bc
Using
FIVE=5 ; echo $FIVE^2 | bc
works just as well (as you actually want the shell to substitute 5 for $FIVE). On some shells you may need to escape/quote the ^ thou...
Sunday, December 10. 2006 at 11:57 (Link) (Reply)
Thanks!
Wednesday, December 13. 2006 at 13:25 (Reply)
model name : Intel(R) Core(TM)2 CPU 6300 @ 1.86GHz
cpu MHz : 600.000
model name : Intel(R) Core(TM)2 CPU 6300 @ 1.86GHz
cpu MHz : 600.000
real 0m30.290s
user 0m30.235s
sys 0m0.040s
Note my cpu is overclocked to 2800GHz, the OS being FC6
Thursday, December 14. 2006 at 16:40 (Reply)
bc benchmark test(?) = bcbench.
time sh -c 'echo "scale=2000; 4*a(1)" | bc -l' > /dev/nul
time sh -c 'echo "scale=2000; e(1)" | bc -l' > /dev/null
Mr.Oshima presentation (BSD Conference Japan at Nagoya,Japan 2005)
http://www.nagoya.bug.gr.jp/~oshima/nbug/etc/bench/index.html (Japanese)
http://www.nagoya.bug.gr.jp/~oshima/nbug/etc/bench/bcbench.html (score and graph) (Japanese)
My English many broken. I am Sorry.
Saturday, November 8. 2008 at 17:47 (Reply)
Monday, March 30. 2009 at 22:49 (Reply)
Your metrics prove it: 13% (12.5% really) is 1/8th of 100%. So yes, you maxxed out the one proc, while the rest where chillin'.
You must be new...
Friday, December 19. 2008 at 11:03 (Reply)
Need help please
How I can compute a arc cosine with bc -l ?
I did not found the syntax or the trick!
thanks a lot
E
Monday, March 30. 2009 at 23:20 (Reply)
(Google FTW)
y = arccos(x) is the equivalent of x = cos(y)
Friday, April 3. 2009 at 21:14 (Reply)
I'd like to calculate pi to 1,000,000 decimal places and save it to a text file... possible using this method ?
I have tried "..." > pi.txt but it just has an empty file.
Suggestions ?
Sunday, April 26. 2009 at 10:26 (Reply)
Saturday, July 25. 2009 at 21:11 (Reply)
produces 6.000000000000000000000000000000000000000000000000000000000000000000\
0000000000000000000000000000000001
I want that "nasty" \ to be removed and the output returns one big line. I know it is possible because long time ago it succeeded me, but i am unfortunately forgotten how...
Thanks in advance and i am looking forward to the solution...
Saturday, July 25. 2009 at 22:47 (Link) (Reply)
$ echo "scale=100;last=10;8/(1+(1/3))"|bc
6.0000000...(etc)...0000001
Saturday, July 25. 2009 at 22:52 (Reply)
(
by the way
Just looked at the source main.c and found the statement:
env_value = getenv ("BC_LINE_LENGTH");
if (env_value != NULL)
{
line_size = atoi (env_value);
if (line_size < 2)
line_size = 70;
}
else
line_size = 70;
always nice to have a change to peek at the source
)
Thursday, September 17. 2009 at 09:53 (Link) (Reply)
what do you type in the command prompt!?!?
Tuesday, May 18. 2010 at 01:44 (Link) (Reply)
echo ' 3 + 3 ' | bc
Try that at a Unix/Linux/Cigwin prompt.
Note single quotes.
Here's a more elaborate version, which puts the answer into a variable "xyzzy" which can be used further along in a command line or shell script (BASH in my case)
$ xyzzy=`echo '1.35 - 1.05' | bc`;\
> echo xyzzy: $xyzzy
xyzzy: .30
NOTE that both the $ and > are system prompts. Note also that the outer quote marks are backticks ie ` while the inner quotes are single quotes ie '
Tuesday, May 4. 2010 at 19:57 (Link) (Reply)
Wednesday, September 29. 2010 at 13:54 (Link) (Reply)
CPUs: 4 x Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz
cpu MHz : 1600.000
real 0m36.001s
user 0m35.940s
sys 0m0.050s
Sunday, October 3. 2010 at 22:54 (Reply)
real 0m44.267s
user 0m43.787s
sys 0m0.008s
and the processor is:
model name : AMD Athlon(tm) 64 X2 Dual Core Processor 4600+
cpu MHz : 2411.319
model name : AMD Athlon(tm) 64 X2 Dual Core Processor 4600+
cpu MHz : 2411.319
I also had Firefox open, i was watching a sitcom and opened WOW with the latest patch emulated through wine.
BTW great article thnx for sharing the info
Thursday, October 14. 2010 at 09:57 (Reply)
Friday, November 26. 2010 at 05:34 (Reply)
Intel(R) Core(TM)2 Duo CPU P8400 @ 2.26GHz
cpu MHz : 0.000
real 0m40.616s
user 0m40.363s
sys 0m0.032s
Wednesday, July 13. 2011 at 20:04 (Reply)
echo "ibase=16;obase=F;104D7" | bc
14BBA
echo "ibase=F;obase=F;104D7" | bc
104D7
Does obase take precedence over ibase and ibase should be in hex?
Wednesday, July 13. 2011 at 21:33 (Reply)
$ echo 'ibase=16;obase=10;FF*FF' | bc
FE01
$ echo 'ibase=16;obase=A;FF*FF' | bc
65025
Sunday, August 7. 2011 at 02:02 (Reply)
user 0m19.468s
sys 0m0.046s
4.2 GHz i2500k
Friday, April 13. 2012 at 11:32 (Reply)
22.20 - 22.10
I want the o/p to be
00.10
instead of jst .10
Pls help asap
Monday, September 10. 2012 at 15:31 (Reply)
Saturday, December 29. 2012 at 19:14 (Reply)