|

Linux CLI 69 🐧 bc in shell scripts

#!/bin/bash

echo "5 + 3" | bc

a=5
b=3
result=$(echo "$a + $b" | bc)
echo "Result: $result"

echo "scale=2; 10 / 3" | bc

echo "sqrt(2)" | bc -l

echo "e(1)" | bc -l

bc <<EOF
scale=4
(5 + 7) * 3
EOF

if result=$(echo "scale=2; 10 / 0" | bc 2>/dev/null); then
  echo "Result: $result"
else
  echo "Error: Division by zero"
fi

Bash arithmetic is integer-only. 10 / 3 gives 3, not 3.33. If you need decimals, square roots, or trigonometric functions, bc is the tool. It’s an arbitrary-precision calculator that reads expressions from stdin and writes results to stdout.

Key point: bc is a full calculator language — variables, functions, loops, conditionals. But in shell scripts you’ll use it mostly for floating-point math and precise decimal arithmetic that $(( )) can’t handle.


a – bc introduction in shell scripts

bc reads input from standard input (stdin) and outputs results to standard output (stdout). You can use it within a shell script by piping expressions to it or by using here documents.

Why bc matters:

Basic arithmetic can be done using $((...)) or expr, but it’s limited to integer operations and does not support decimal precision or advanced mathematical functions like square roots. bc is more versatile in such cases.

Feature$(( ))bc
Integer arithmetic
Floating point
Square roots
Exponentials
Trig functions✅ (with -l)
Precision control✅ (scale)
Arbitrary precision
SpeedFastestSlower
External processNoYes

In summary, bc is a powerful tool for advanced mathematical operations in shell scripts, especially for:

  • Floating-point calculations
  • Complex expressions (e.g., square root, exponentials)
  • Precise decimal arithmetic using scale

Basic usage:

# Pipe an expression
$ echo "5 + 3" | bc
[ 8 ]

# Use a here string
$ bc <<< "5 + 3"
[ 8 ]

# Use a here document
$ bc << EOF
5 + 3
EOF
[ 8 ]

# Interactive
$ bc
5 + 3
8
^D

The scale variable:

scale controls how many decimal places bc produces for division and other operations. Default is 0 — integer results only.

$ echo "10 / 3" | bc
[ 3 ]

$ echo "scale=2; 10 / 3" | bc
[ 3.33 ]

$ echo "scale=5; 10 / 3" | bc
[ 3.33333 ]

$ echo "scale=10; 10 / 3" | bc
[ 3.3333333333 ]

You can set scale once at the top of a here document and it applies to all following lines:

$ bc << EOF
scale=4
10 / 3
20 / 3
1 / 7
EOF
[ 3.3333 ]
[ 6.6666 ]
[ .1428 ]

Note: scale affects division and some transcendental functions. Multiplication and addition of integers aren’t affected.

The -l flag — the math library:

bc -l loads the standard math library, which adds:

FunctionMeaning
s(x)Sine
c(x)Cosine
a(x)Arctangent
l(x)Natural log
e(x)Exponential (e^x)
sqrt(x)Square root
j(n,x)Bessel function

It also sets scale to 20 by default:

$ echo "sqrt(2)" | bc -l
[ 1.41421356237309504880 ]

$ echo "scale=4; sqrt(2)" | bc -l
[ 1.4142 ]

$ echo "e(1)" | bc -l
[ 2.71828182845904523536 ]

Interactive vs scripted:

bc can be used interactively (great for quick math) or in scripts (great for calculation). In scripts, always pipe or use a here document — bc doesn’t like being called with a bare expression argument.

# ❌ Doesn't work — bc ignores the argument
$ bc "5 + 3"

# ✅ Correct — pipe or here string
$ echo "5 + 3" | bc
$ bc <<< "5 + 3"

Variables in bc:

bc has its own variables, separate from bash:

$ bc << EOF
a = 5
b = 3
a + b
a * b
EOF
[ 8 ]
[ 15 ]

You can pass bash variables into bc by interpolating them in the string:

$ a=5
$ b=3
$ echo "$a + $b" | bc
[ 8 ]

Important: Use double quotes so bash expands $a and $b before passing to bc. Single quotes would send $a + $b literally, and bc would complain about the $ symbol.

Comparison and conditional:

bc supports comparisons that return 1 (true) or 0 (false):

$ echo "5 > 3" | bc
[ 1 ]
$ echo "5 < 3" | bc
[ 0 ]
$ echo "5 == 5" | bc
[ 1 ]

These are useful for tests, though in shell scripts you’d usually use (( )) or [[ ]] for integer comparisons. bc shines when the comparison involves floats:

$ echo "3.14 > 3.13" | bc
[ 1 ]

$ if [ "$(echo "3.14 > 3.13" | bc)" -eq 1 ]; then
>     echo "3.14 is bigger"
> fi
[ 3.14 is bigger ]

Base conversion with bc:

bc can also convert between bases using ibase and obase:

$ echo "obase=2; 26" | bc
[ 11010 ]

$ echo "ibase=16; 1A" | bc
[ 26 ]

$ echo "ibase=2; obase=16; 11010" | bc
[ 1A ]

b – bc examples in shell scripts

Here are the seven examples from the top of the chapter, explained one by one.

Example 1 — Simple arithmetic:

echo "5 + 3" | bc
[ 8 ]

The simplest form — an expression piped in, the result piped out. bc reads 5 + 3, computes it, and prints 8.

Example 2 — Using variables:

a=5
b=3
result=$(echo "$a + $b" | bc)
echo "Result: $result"
[ Result: 8 ]

Bash variables are expanded into the string before bc sees it. The $(...) captures bc‘s output. Note the double quotes — they let bash expand $a and $b.

Compare with single quotes:

$ a=5
$ b=3
$ echo '$a + $b' | bc
[ (standard_in) 1: syntax error ]

bc doesn’t understand $a — it’s a shell construct, not bc syntax.

Example 3 — Division with two decimal places:

echo "scale=2; 10 / 3" | bc
[ 3.33 ]

Without scale, 10 / 3 gives 3 (integer division). With scale=2, it gives 3.33. Use semicolons to separate multiple statements on one line.

Example 4 — Square root:

echo "sqrt(2)" | bc -l
[ 1.41421356237309504880 ]

-l loads the math library, enabling sqrt(). The default scale with -l is 20, so you get 20 digits of precision. To control it:

$ echo "scale=4; sqrt(2)" | bc -l
[ 1.4142 ]

Example 5 — Exponential:

echo "e(1)" | bc -l
[ 2.71828182845904523536 ]

e(x) computes e^x. e(1) gives Euler’s number (≈ 2.71828). Again, -l is required.

Example 6 — Using here documents:

bc <<EOF
scale=4
(5 + 7) * 3
EOF
[ 36 ]

A here document lets you pass multiple lines to bc. The scale=4 sets precision for the session; (5 + 7) * 3 evaluates to 36. Here documents are the cleanest way to run multi-statement bc sessions.

Example 7 — Error handling:

if result=$(echo "scale=2; 10 / 0" | bc 2>/dev/null); then
  echo "Result: $result"
else
  echo "Error: Division by zero"
fi
[ Error: Division by zero ]

bc doesn’t exit non-zero on division by zero — it prints an error message to stderr and returns 0. So to detect the error, you check bc‘s output and stderr:

$ echo "10 / 0" | bc
[ Runtime error (func=(main), adr=4): Divide by zero ]
$ echo $?
[ 0 ]

The 2>/dev/null hides the error from the terminal. The if checks whether result is non-empty — but that’s not quite right, because bc prints nothing on success in some cases. A better approach:

if result=$(echo "scale=2; 10 / 0" | bc 2>/dev/null) && [ -n "$result" ]; then
    echo "Result: $result"
else
    echo "Error"
fi

Or check stderr explicitly:

if ! output=$(echo "scale=2; 10 / 0" | bc 2>&1 >/dev/null) ; then
    echo "Error: $output"
fi

Actually the cleanest way is to validate the input before passing it to bc:

divisor=0
if [ "$divisor" -eq 0 ]; then
    echo "Error: division by zero" >&2
    exit 1
fi
echo "scale=2; 10 / $divisor" | bc

Tip: bc is forgiving — it prints errors to stderr but still returns 0. Don’t rely on $? alone; check the output or the stderr.

More bc examples:

# Compute average
total=175
count=4
avg=$(echo "scale=2; $total / $count" | bc)
echo "Average: $avg"
[ Average: 43.75 ]

# Circle area
radius=5
pi=$(echo "scale=10; 4*a(1)" | bc -l)    # atan(1)*4 = pi
area=$(echo "scale=2; $pi * $radius * $radius" | bc)
echo "Area: $area"
[ Area: 78.53 ]

# Compound interest
principal=1000
rate=0.05
years=10
amount=$(echo "scale=2; $principal * e($rate * $years)" | bc -l)
echo "Amount: $amount"

# Percentage
part=25
whole=200
pct=$(echo "scale=1; $part * 100 / $whole" | bc)
echo "$pct%"
[ 12.5% ]

# Comparison
a=3.14
b=3.13
if [ "$(echo "$a > $b" | bc)" -eq 1 ]; then
    echo "$a > $b"
fi
[ 3.14 > 3.13 ]

# Round to nearest integer
x=3.7
echo "($x + 0.5) / 1" | bc
[ 4 ]

# Absolute value
x=-5
echo "if ($x < 0) -$x else $x" | bc
[ 5 ]

# Min/max
a=10
b=20
echo "if ($a < $b) $a else $b" | bc    # min
[ 10 ]
echo "if ($a > $b) $a else $b" | bc    # max
[ 20 ]

# Power
echo "2^10" | bc
[ 1024 ]

# Modulus (works on floats too!)
echo "scale=2; 10.5 % 3" | bc
[ 1.50 ]

Multi-statement here documents:

bc << EOF
scale=4

# Rectangle
w = 5.5
h = 3.2
area = w * h
perimeter = 2 * (w + h)
"Area: " ; area
"Perimeter: " ; perimeter
EOF
[ Area: 17.6000 ]
[ Perimeter: 17.4000 ]

Strings in double quotes are printed literally, and ; separates statements.

Using bc with a script file:

For complex calculations, put the bc code in a file and invoke it:

$ cat > calc.bc << 'EOF'
scale=4
define f(x) {
    return x * x + 2 * x + 1
}
f(3)
EOF

$ bc -l calc.bc
[ 16.0000 ]

bc supports user-defined functions with define. This is rarely needed in shell scripts, but it’s there if you need it.


c – bc tips in shell scripts

Tip 1 — Quoting expressions:

Always use double quotes when passing bash variable expressions to bc — otherwise the shell won’t expand the variables, or it will expand them in unexpected ways.

# ❌ Single quotes — bc sees literal $a
$ echo '$a + $b' | bc
[ syntax error ]

# ✅ Double quotes — bash expands $a and $b
$ echo "$a + $b" | bc
[ 8 ]

# ⚠️ Unquoted — word splitting can break things
$ echo $a + $b | bc
[ 8 ]               # works here, but fragile

For complex expressions with special characters, quote the whole thing:

$ echo "scale=2; $a * ($b + 1)" | bc

Tip 2 — Setting scale:

For precise decimal output, always set scale explicitly. The default is 0, which truncates everything after the decimal point.

# ❌ Default scale — integer result
$ echo "10 / 3" | bc
[ 3 ]

# ✅ Explicit scale
$ echo "scale=2; 10 / 3" | bc
[ 3.33 ]

# ✅ With -l, default scale is 20
$ echo "10 / 3" | bc -l
[ 3.33333333333333333333 ]

If you want a specific precision, put it first:

$ echo "scale=4; 10 / 3" | bc
[ 3.3333 ]

Tip 3 — Error handling:

bc prints errors to stderr but returns exit code 0. Don’t rely on $? alone. Use one of these approaches:

# Approach 1: Capture stderr and check
if ! err=$(echo "10 / 0" | bc -l 2>&1 >/dev/null); then
    echo "Error: $err" >&2
fi

# Approach 2: Validate input first
if [ "$divisor" -eq 0 ]; then
    echo "Error: division by zero" >&2
    exit 1
fi
echo "scale=2; $numerator / $divisor" | bc

# Approach 3: Check output isn't empty or an error string
result=$(echo "scale=2; 10 / 0" | bc 2>/dev/null)
if [ -z "$result" ] || [[ "$result" == *error* ]]; then
    echo "Calculation failed"
fi

The cleanest approach in most scripts is input validation — check before you call bc.

Tip 4 — Use -l for the math library:

When you need sqrt(), e(), l() (log), or trig functions, pass -l. Without it, bc doesn’t know them.

$ echo "sqrt(2)" | bc
[ syntax error ]

$ echo "sqrt(2)" | bc -l
[ 1.41421356237309504880 ]

Tip 5 — Here documents for complex sessions:

When you have multiple calculations or want to set scale once, use a here document:

bc << EOF
scale=4
a = 10
b = 3
a / b
a * b
a - b
EOF

This avoids repeating scale= on every line.

Tip 6 — Trailing newline:

bc outputs a newline after each result. When using $(...), the trailing newline is stripped automatically:

$ result=$(echo "5 + 3" | bc)
$ echo "[$result]"
[ [8] ]             # no trailing newline inside

Tip 7 — Avoid bc for integer arithmetic:

For integers, use $(( )) — it’s faster and doesn’t spawn a process:

# ❌ Slower — spawns bc
$ result=$(echo "$a + $b" | bc)

# ✅ Faster — built-in
$ result=$((a + b))

Use bc only when you need floats or math functions.

Tip 8 — Watch out for locale:

bc uses . as the decimal separator regardless of locale. If your script expects a comma (e.g., 3,14), you’ll need to convert.

$ LC_ALL=de_DE.UTF-8 echo "3.14 + 1" | bc
[ 4.14 ]            # still uses .

Putting the tips together:

#!/bin/bash

# Validate input first
numerator=10
divisor=0

if [ "$divisor" -eq 0 ]; then
    echo "Error: division by zero" >&2
    exit 1
fi

# Use double quotes and explicit scale
result=$(echo "scale=2; $numerator / $divisor" | bc 2>/dev/null)

# Verify we got something
if [ -z "$result" ]; then
    echo "Calculation failed" >&2
    exit 1
fi

echo "Result: $result"

A complete error-handling pattern:

#!/bin/bash

calc() {
    local expr="$1"
    local result
    local error

    error=$(echo "$expr" | bc -l 2>&1 >/dev/null)
    result=$(echo "$expr" | bc -l 2>/dev/null)

    if [ -n "$error" ]; then
        echo "Error: $error" >&2
        return 1
    fi

    echo "$result"
}

if result=$(calc "scale=2; 10 / 3"); then
    echo "Result: $result"
fi

By integrating bc into your scripts, you can handle a wide range of numerical problems that go beyond the standard shell arithmetic capabilities.


Complete Example Session

# ============================================
# PART 1: BASIC
# ============================================

$ echo "5 + 3" | bc
[ 8 ]

$ bc <<< "5 + 3"
[ 8 ]

# ============================================
# PART 2: VARIABLES
# ============================================

$ a=5
$ b=3
$ result=$(echo "$a + $b" | bc)
$ echo "Result: $result"
[ Result: 8 ]

# ============================================
# PART 3: SCALE
# ============================================

$ echo "10 / 3" | bc
[ 3 ]
$ echo "scale=2; 10 / 3" | bc
[ 3.33 ]
$ echo "scale=5; 10 / 3" | bc
[ 3.33333 ]

# ============================================
# PART 4: -l MATH LIBRARY
# ============================================

$ echo "sqrt(2)" | bc -l
[ 1.41421356237309504880 ]
$ echo "scale=4; sqrt(2)" | bc -l
[ 1.4142 ]

$ echo "e(1)" | bc -l
[ 2.71828182845904523536 ]

$ echo "scale=10; 4*a(1)" | bc -l    # pi
[ 3.1415926535 ]

# ============================================
# PART 5: HERE DOCUMENT
# ============================================

$ bc << EOF
> scale=4
> (5 + 7) * 3
> 10 / 3
> EOF
[ 36 ]
[ 3.3333 ]

# ============================================
# PART 6: ERROR HANDLING
# ============================================

$ echo "10 / 0" | bc
[ Runtime error (func=(main), adr=4): Divide by zero ]
$ echo $?
[ 0 ]

$ if result=$(echo "scale=2; 10 / 0" | bc 2>/dev/null); then
>   echo "Result: $result"
> else
>   echo "Error: Division by zero"
> fi
[ Error: Division by zero ]

# ============================================
# PART 7: AVERAGE
# ============================================

$ total=175
$ count=4
$ avg=$(echo "scale=2; $total / $count" | bc)
$ echo "Average: $avg"
[ Average: 43.75 ]

# ============================================
# PART 8: PERCENTAGE
# ============================================

$ part=25
$ whole=200
$ pct=$(echo "scale=1; $part * 100 / $whole" | bc)
$ echo "$pct%"
[ 12.5% ]

# ============================================
# PART 9: FLOAT COMPARISON
# ============================================

$ echo "3.14 > 3.13" | bc
[ 1 ]

$ if [ "$(echo "3.14 > 3.13" | bc)" -eq 1 ]; then
>     echo "yes"
> fi
[ yes ]

# ============================================
# PART 10: ROUNDING
# ============================================

$ x=3.7
$ echo "($x + 0.5) / 1" | bc
[ 4 ]

$ x=3.4
$ echo "($x + 0.5) / 1" | bc
[ 3 ]

# ============================================
# PART 11: MIN/MAX
# ============================================

$ a=10
$ b=20
$ echo "if ($a < $b) $a else $b" | bc
[ 10 ]
$ echo "if ($a > $b) $a else $b" | bc
[ 20 ]

# ============================================
# PART 12: FLOATS IN MODULUS
# ============================================

$ echo "scale=2; 10.5 % 3" | bc
[ 1.50 ]

# ============================================
# PART 13: POWER
# ============================================

$ echo "2^10" | bc
[ 1024 ]

# ============================================
# PART 14: CIRCLE AREA
# ============================================

$ radius=5
$ pi=$(echo "scale=10; 4*a(1)" | bc -l)
$ area=$(echo "scale=2; $pi * $radius * $radius" | bc)
$ echo "Area: $area"
[ Area: 78.53 ]

# ============================================
# PART 15: ABSOLUTE VALUE
# ============================================

$ x=-5
$ echo "if ($x < 0) -$x else $x" | bc
[ 5 ]

# ============================================
# PART 16: BASE CONVERSION
# ============================================

$ echo "obase=2; 26" | bc
[ 11010 ]
$ echo "ibase=16; 1A" | bc
[ 26 ]

# ============================================
# PART 17: FULL SCRIPT
# ============================================

$ cat > bc-examples.sh << 'EOF'
#!/bin/bash

echo "5 + 3" | bc

a=5
b=3
result=$(echo "$a + $b" | bc)
echo "Result: $result"

echo "scale=2; 10 / 3" | bc

echo "sqrt(2)" | bc -l

echo "e(1)" | bc -l

bc <<EOF2
scale=4
(5 + 7) * 3
EOF2

if result=$(echo "scale=2; 10 / 0" | bc 2>/dev/null); then
  echo "Result: $result"
else
  echo "Error: Division by zero"
fi
EOF
$ chmod +x bc-examples.sh
$ ./bc-examples.sh
[ 8 ]
[ Result: 8 ]
[ 3.33 ]
[ 1.41421356237309504880 ]
[ 2.71828182845904523536 ]
[ 36 ]
[ Error: Division by zero ]

Quick Reference

bc Basics

CommandMeaning
echo "EXPR" | bcEvaluate expression
bc <<< "EXPR"Here string
bc << EOF ... EOFHere document
bc -lLoad math library
bc file.bcRun a bc script file

bc Variables

VariableMeaningDefault
scaleDecimal places0
ibaseInput base10
obaseOutput base10
lastLast result

bc Operators

OperatorMeaning
+Addition
-Subtraction
*Multiplication
/Division
%Modulus
^Power
++ / --Increment / decrement
+= -= *= /=Compound assignment
== != < <= > >=Comparison
&& || !Logical

bc Math Library (-l)

FunctionMeaning
s(x)Sine
c(x)Cosine
a(x)Arctangent
l(x)Natural log
e(x)e^x
sqrt(x)Square root
j(n,x)Bessel

bc vs $(( ))

Feature$(( ))bc
Integers
Floats
scale control
sqrt, e, log✅ (with -l)
Arbitrary precision
SpeedFastestSlower
External processNoYes

Common Patterns

PatternExample
Simple mathecho "5 + 3" | bc
With variablesecho "$a + $b" | bc
With scaleecho "scale=2; $a / $b" | bc
Square rootecho "sqrt($x)" | bc -l
Multi-linebc << EOF ... EOF
Captureresult=$(echo "..." | bc)
Float compareecho "$a > $b" | bc

Best Practices

Do This:

# Quote expressions with double quotes
echo "$a + $b" | bc                   # ✅

# Always set scale for division
echo "scale=2; $a / $b" | bc          # ✅

# Use -l for sqrt, e, log
echo "sqrt(2)" | bc -l                # ✅

# Use here documents for multiple statements
bc << EOF
scale=4
$a / $b
$a * $b
EOF                                    # ✅

# Validate divisors before dividing
[ "$b" -eq 0 ] && { echo "div by zero"; exit 1; }
echo "scale=2; $a / $b" | bc          # ✅

# Use $(( )) for integers
result=$((a + b))                     # ✅

# Capture output with $()
result=$(echo "scale=2; $a / $b" | bc)  # ✅

# Use here strings for short expressions
result=$(bc <<< "scale=2; $a / $b")   # ✅

Don’t Do This:

# Don't use single quotes with variables
echo '$a + $b' | bc                   # ❌ syntax error

# Don't forget scale for division
echo "10 / 3" | bc                    # ❌ gives 3

# Don't use bc for integers
result=$(echo "$a + $b" | bc)         # ⚠️  use $((a+b))

# Don't expect non-zero exit on error
echo "10 / 0" | bc; echo $?           # ⚠️  prints 0

# Don't forget -l for math functions
echo "sqrt(2)" | bc                   # ❌ syntax error

# Don't call bc with a bare argument
bc "5 + 3"                            # ❌ ignores the argument

# Don't use bc for base64 or hex strings
echo "obase=16; FF" | bc              # ⚠️  FF isn't decimal

# Don't assume locale decimal separator
echo "3,14 + 1" | bc                  # ❌ syntax error

Common Pitfalls

PitfallProblemSolution
Single quotesVars not expandedUse double quotes
No scaleInteger divisionSet scale=N
No -lMath functions failAdd -l
Division by zeroSilent errorValidate input
bc exit code 0Error not caughtCheck stderr/output
bc "expr"Argument ignoredPipe or here string
Trailing newlineExtra in output$() strips it
Locale comma3,14 errorsbc uses . always

Real-World Examples

1. Simple Arithmetic

#!/bin/bash
echo "5 + 3" | bc
[ 8 ]

2. Using Variables

#!/bin/bash
a=5
b=3
result=$(echo "$a + $b" | bc)
echo "Result: $result"
[ Result: 8 ]

3. Division with Decimals

#!/bin/bash
echo "scale=2; 10 / 3" | bc
[ 3.33 ]

4. Square Root

#!/bin/bash
echo "sqrt(2)" | bc -l
[ 1.41421356237309504880 ]

5. Exponential

#!/bin/bash
echo "e(1)" | bc -l
[ 2.71828182845904523536 ]

6. Here Document

#!/bin/bash
bc << EOF
scale=4
(5 + 7) * 3
EOF
[ 36 ]

7. Error Handling

#!/bin/bash
if result=$(echo "scale=2; 10 / 0" | bc 2>/dev/null); then
  echo "Result: $result"
else
  echo "Error: Division by zero"
fi
[ Error: Division by zero ]

8. Average of Numbers

#!/bin/bash
total=175
count=4
avg=$(echo "scale=2; $total / $count" | bc)
echo "Average: $avg"
[ Average: 43.75 ]

9. Percentage

#!/bin/bash
part=25
whole=200
pct=$(echo "scale=1; $part * 100 / $whole" | bc)
echo "$pct%"
[ 12.5% ]

10. Circle Area

#!/bin/bash
radius=5
pi=$(echo "scale=10; 4*a(1)" | bc -l)
area=$(echo "scale=2; $pi * $radius * $radius" | bc)
echo "Area: $area"
[ Area: 78.53 ]

11. Compound Interest

#!/bin/bash
p=1000
r=0.05
t=10
amount=$(echo "scale=2; $p * e($r * $t)" | bc -l)
echo "Amount: $amount"
[ Amount: 1648.72 ]

12. Float Comparison

#!/bin/bash
a=3.14
b=3.13
if [ "$(echo "$a > $b" | bc)" -eq 1 ]; then
    echo "$a > $b"
fi
[ 3.14 > 3.13 ]

13. Round to Integer

#!/bin/bash
x=3.7
result=$(echo "($x + 0.5) / 1" | bc)
echo "$result"
[ 4 ]

14. Absolute Value

#!/bin/bash
x=-5
echo "if ($x < 0) -$x else $x" | bc
[ 5 ]

15. Min and Max

#!/bin/bash
a=10
b=20
echo "Min: $(echo "if ($a < $b) $a else $b" | bc)"
echo "Max: $(echo "if ($a > $b) $a else $b" | bc)"
[ Min: 10 ]
[ Max: 20 ]

16. Power

#!/bin/bash
echo "2^10" | bc
[ 1024 ]

17. Float Modulus

#!/bin/bash
echo "scale=2; 10.5 % 3" | bc
[ 1.50 ]

18. Sum a List

#!/bin/bash
sum=0
for n in 1.5 2.5 3.0 4.25; do
    sum=$(echo "$sum + $n" | bc)
done
echo "Sum: $sum"
[ Sum: 11.25 ]

19. Interactive Calculator

#!/bin/bash
while true; do
    read -p "calc> " expr
    [ "$expr" = "quit" ] && break
    echo "$expr" | bc -l
done

20. Full Example Script

#!/bin/bash

# Simple arithmetic
echo "5 + 3" | bc

# Variables
a=5
b=3
result=$(echo "$a + $b" | bc)
echo "Result: $result"

# Division with scale
echo "scale=2; 10 / 3" | bc

# Square root
echo "sqrt(2)" | bc -l

# Exponential
echo "e(1)" | bc -l

# Here document
bc <<EOF
scale=4
(5 + 7) * 3
EOF

# Error handling
if result=$(echo "scale=2; 10 / 0" | bc 2>/dev/null); then
  echo "Result: $result"
else
  echo "Error: Division by zero"
fi

Visual: bc vs $(( ))

┌──────────────────────────────────────────────┐
│           $(( )) — integer only              │
│                                              │
│  $ echo $((10 / 3))                          │
│  [ 3 ]                                       │
│                                              │
│  Fast, built-in                              │
│  No decimals, no sqrt, no e()                │
│                                              │
└──────────────────────────────────────────────┘

┌──────────────────────────────────────────────┐
│           bc — arbitrary precision           │
│                                              │
│  $ echo "scale=2; 10 / 3" | bc               │
│  [ 3.33 ]                                    │
│                                              │
│  $ echo "sqrt(2)" | bc -l                    │
│  [ 1.41421356237309504880 ]                  │
│                                              │
│  Slower, spawns a process                    │
│  Decimals, sqrt, e, log, trig                │
│                                              │
└──────────────────────────────────────────────┘

Visual: bc Pipeline

┌──────────────────────────────────────────────┐
│           bc pipeline                        │
│                                              │
│  echo "scale=2; 10/3"                        │
│       │                                      │
│       │  (stdin)                             │
│       ▼                                      │
│  ┌──────────────────┐                        │
│  │       bc         │  ← reads expression    │
│  │                  │  ← evaluates           │
│  └────────┬─────────┘                        │
│           │                                  │
│           │  (stdout)                        │
│           ▼                                  │
│      3.33                                    │
│                                              │
│  Capture with $()                            │
│  result=$(echo "..." | bc)                   │
│                                              │
└──────────────────────────────────────────────┘

Summary

CommandPurposeExample
echo "E" | bcEvaluate expressionecho "5 + 3" | bc
bc <<< "E"Here stringbc <<< "5 + 3"
bc << EOF ... EOFHere documentMulti-line
bc -lMath libraryecho "sqrt(2)" | bc -l
scale=NDecimal placesecho "scale=2; 10/3" | bc
a=5; a+3Variables in bcecho "a=5; a+3" | bc
$a + $bBash varsecho "$a + $b" | bc
sqrt(x)Square rootbc -l
e(x)Exponentialbc -l
l(x)Natural logbc -l
a(x)Arctangentbc -l
s(x) / c(x)Sine / cosinebc -l
ibase=NInput baseecho "ibase=16; 1A" | bc
obase=NOutput baseecho "obase=2; 26" | bc

Key takeaways:

  • bc is for floating-point and precise decimal arithmetic — the things $(( )) can’t do
  • echo "EXPR" \| bc is the primary pattern; bc <<< "EXPR" and here documents also work
  • Always set scale for decimal output — default is 0 (integer only)
  • Use -l for the math library — sqrt(), e(), l(), trig functions
  • Quote with double quotes when using bash variables — "$a + $b", not '$a + $b'
  • bc exits 0 even on errors — validate input or check stderr
  • Here documents are best for multi-line bc sessions
  • Use $(( )) for integersbc is slower because it spawns a process
  • bc supports variables, functions, loops, and conditionals — it’s a full language
  • Common uses: averages, percentages, circle geometry, compound interest, float comparisons
  • ibase and obase let bc convert between number bases as a bonus

Remember: When $(( )) runs out of precision, reach for bc. Pipe an expression in, capture the result with $(...). Set scale for decimals. Use -l for math functions. Quote with double quotes. And validate your input — bc won’t tell you it failed. Master bc, and your shell scripts can do real math.


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!