opscape

Text processing

bc

An arbitrary-precision calculator language, used from scripts for decimal math the shell cannot do.

bc [-lqs] [FILE...]

11 of 11 examples run in Debian 13.7 on 2026-10-31 · manual: bc(1)

bash arithmetic, $(( )), only knows integers. When a script needs decimals, very large numbers or base conversion, the usual answer is to pipe an expression into bc: it reads statements from standard input or files, evaluates them, and prints each result.

Two settings explain almost every surprise. scale is the number of digits kept after the decimal point in division and other operations, and it starts at 0, so 10 / 3 is 3. Starting bc with -l loads the math library, sets scale to 20 and adds s(), c(), a(), l(), e() (sine, cosine, arctangent, natural log, exponential). Results are truncated to scale, not rounded.

For simple float formatting awk or printf '%.2f' is often enough; reach for bc when you need exact decimal arithmetic or numbers larger than 64 bits.

Examples

Evaluate an expression

echo '2 + 3 * 4' | bc
explain
output
14

bc follows the usual precedence, so multiplication happens first and the result is 14.

Division is integer until you set scale

echo '10 / 3' | bc
echo 'scale=2; 10 / 3' | bc
output
3
3.33

With the default scale of 0 the fraction is dropped. scale=2 keeps two decimal places. Statements are separated by ; or newlines.

Use the math library with -l

echo '10 / 3; sqrt(2); 4 * a(1)' | bc -l
explain
output
3.33333333333333333333
1.41421356237309504880
3.14159265358979323844

-l sets scale to 20 and loads the math functions. a(1) is the arctangent of 1, a quarter of pi, so 4 * a(1) prints pi to 20 decimal places. sqrt is built in and also honors scale.

Use the result in a shell script

units=92; revenue=743.36
avg=$(echo "scale=2; $revenue / $units" | bc)
echo "average price: $avg"
output
average price: 8.08

Double quotes let the shell insert the variables into the expression, and command substitution captures the answer. bc omits the leading zero for values below 1, which is why the result prints as 8.08 here but would be .50 for a half.

bc truncates instead of rounding

echo 'scale=2; 2 / 3' | bc
printf '%.2f\n' "$(echo 'scale=10; 2 / 3' | bc)"
output
.66
0.67

With scale=2 the result is cut to .66. To round, compute with extra digits and let printf round to the precision you want, giving 0.67 (with the leading zero restored).

Compare decimal numbers

load=3.75; limit=2.5
if (( $(echo "$load > $limit" | bc) )); then echo "load $load is over $limit"; fi
output
load 3.75 is over 2.5

bash's [ ] and (( )) only compare integers. bc prints 1 for a true comparison and 0 for false, which (( )) then tests.

Add up a column of numbers

paste -sd+ data/numbers.txt | bc
explain
output
324

paste -sd+ joins the lines of the file with + into one expression, 42+7+19+..., and bc evaluates it. Works for decimals too, unlike $(( )).

Calculate with very large numbers

echo '2^100; 2^64 - 1' | bc
explain
output
1267650600228229401496703205376
18446744073709551615

bc's precision is limited only by memory. bash arithmetic would overflow at 64 bits; 2^64 - 1 is the largest unsigned 64-bit integer. ^ takes integer exponents only.

Convert between number bases

echo 'obase=16; 255' | bc
echo 'obase=2; 10' | bc
echo 'ibase=16; FF' | bc
output
FF
1010
255

obase sets the output base and ibase the input base. Hex digits must be uppercase. Set obase before ibase: once ibase=16, a later obase=10 would be read as hex 10, which is 16.

Run a multi-line calculation

bc -l <<'EOF'
principal = 10000
rate = 0.05
years = 10
total = principal * e(years * l(1 + rate))
scale = 2
total / 1
EOF
output
16288.94

bc is a small language with variables, if, while, for and functions. This computes compound interest: l() is the natural log and e() the exponential, so total is principal times (1 + rate) to the power of years, worked out at 20 digits. Only then is scale lowered; dividing by 1 applies it and truncates to cents. Setting scale = 2 at the top would make l() and e() work at two digits and print a badly wrong 14900.00.

Errors do not change the exit status

echo '1 / 0' | bc; echo "exit status: $?"
explain
output
Runtime error (func=(main), adr=3): Divide by zero
exit status: 0

bc prints a runtime error on stderr but still exits with status 0. Scripts must check the output, for example that it is non-empty, rather than rely on $?.

Common pitfalls

  • scale defaults to 0, so echo '7/2' | bc prints 3. Set scale or use -l.

  • Results below 1 have no leading zero (.5). Pass the value through printf '%.2f' if something downstream expects 0.5.

  • Long results are wrapped with a backslash at 70 characters. GNU bc reads BC_LINE_LENGTH; BC_LINE_LENGTH=0 turns wrapping off.

  • ibase affects every later number, including the ones in obase=.... Set obase first.

  • Errors such as division by zero or a syntax error print a message but leave the exit status at 0.

GNU vs BSD and macOS

The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).

  • Debian and Ubuntu ship GNU bc; recent macOS and FreeBSD ship a different implementation (Gavin Howard's bc). Both accept the POSIX language and -l, but their error messages and non-POSIX extensions differ, so test scripts on both if you rely on extensions.

Options worth knowing

A selection, described in our own words. For the full list, see bc(1) or bc --help.

OptionWhat it does
-l, --mathlibLoad the math library and set scale to 20.
-q, --quietDo not print the welcome banner in interactive mode.
-s, --standardProcess exactly the POSIX bc language.
-w, --warnWarn about extensions to POSIX bc.
-i, --interactiveForce interactive mode.

Related