keepcalculator

06 Numbers and Powers

Mathematical Operations in Shell Scripting

Card No. 06·66177 · Updated · Standard formula, shown below

The calculator on this card is switched off while it is checked. The formula is below, and the worked example shows how to do the sum by hand.

Mathematical operations in shell scripting are performed using built-in arithmetic expansion, the expr command, or external tools like bc and awk. You enter numbers and operators, and the shell returns the computed result, which you can store in a variable or print directly. This article explains each method, when to use it, and common pitfalls.

Formula

The calculator above demonstrates the core arithmetic operations available in shell arithmetic expansion: addition, subtraction, multiplication, division, and modulo (remainder). The general syntax is $(( expression )), where expression uses standard operators: + (addition), - (subtraction), * (multiplication), / (integer division), and % (modulo). The shell evaluates the expression using integer arithmetic (unless you use a tool like bc for floating point).

Variables are referenced without the dollar sign inside the double parentheses. For example, $((a + b)) adds the values of a and b. The result is always an integer (unless you use bc or awk).

Worked Example

Using the default values from the calculator: a = 10 and b = 3.

  • Sum: 10 + 3 = 13
  • Product: 10 * 3 = 30
  • Quotient: 10 / 3 = 3 (integer division truncates the decimal)
  • Remainder: 10 % 3 = 1 (since 3 goes into 10 three times with 1 left over)

The calculator shows these results: Sum = 13, Product = 30, Quotient = 3, Remainder = 1.

Background: Why Shell Arithmetic Matters

Shell scripts often need to count iterations, compute file sizes, or generate numeric sequences. Without arithmetic, you would have to call external programs for every calculation, which is slower and more error-prone. The Bourne shell (sh) originally had no built-in arithmetic, so scripts used the expr command. POSIX sh later added arithmetic expansion, and Bash extended it with C-style syntax. Knowing the available methods helps you choose the most efficient one for your script.

How It Works: The Three Main Approaches

There are three primary ways to do math in a shell script:

  • Arithmetic expansion: $(( expression )) – built into POSIX shells, handles integers only.
  • The expr command: expr 10 + 3 – external command, works in all shells, but slow and requires escaping operators in some cases.
  • External tools: bc for floating point, awk for complex math, let (Bash built-in) for assignments.

For most scripts, arithmetic expansion is the best choice because it is fast, portable, and readable. For floating-point math, bc is the standard tool, while awk is useful when you already have a data-processing pipeline.

How to Choose the Right Method

Select the method based on your needs:

  • Integer arithmetic (counting, indexing): use $(( )).
  • Floating-point arithmetic (percentages, averages): use bc or awk.
  • Portability across all shells (including dash): use expr or POSIX arithmetic expansion (both are POSIX, but expr is more universally available in older systems).
  • Performance in loops: arithmetic expansion is faster than calling expr repeatedly.

Example: if you need to compute 1/3, $((1/3)) gives 0, but echo "scale=2; 1/3" | bc gives 0.33.

Common Problems and Pitfalls

Several mistakes are common when doing math in shell scripts:

  • Spaces in arithmetic expansion: $(( 10 + 3 )) works, but $((10+3)) also works. However, $((10 + 3 )) with a space before the closing parenthesis causes an error in some shells.
  • Using * without escaping in expr: expr 10 * 3 fails because * is a wildcard. You must escape it: expr 10 \* 3.
  • Integer division truncation: $((10/3)) gives 3, not 3.33. If you need decimals, use bc.
  • Overflow: Shell arithmetic uses fixed-width integers (usually 64-bit). Very large numbers can wrap around.
  • Division by zero: Causes an error. Check that the divisor is not zero before dividing.

Floating-Point Math with bc and awk

When you need non-integer results, the shell’s built-in arithmetic is not enough. The bc command is a calculator that reads expressions from standard input. For example:

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

Output: 3.33

The scale variable sets the number of decimal places. awk is another option, especially when you have a stream of numbers:

echo "10 3" | awk '{print $1/$2}'

Output: 3.33333 (default precision).

Both tools are widely available on Unix-like systems, but note that bc is not always installed by default on minimal systems.

Comparing Performance and Portability

Performance matters in loops that run thousands of times. Arithmetic expansion is built into the shell, so it is the fastest. expr forks a new process each time, which is much slower. bc and awk also fork processes, so they are slower still. For portability, POSIX arithmetic expansion is supported by all modern shells, but expr is more portable to very old systems. In practice, use arithmetic expansion for integers and bc for floating point; avoid expr unless you need maximum compatibility.

Frequently Asked Questions

Can I do floating-point math in Bash without bc?

No, Bash’s built-in arithmetic only handles integers. You can use awk or bc for floating-point. Some shells like zsh support floating-point natively, but Bash does not.

Why does $((10/3)) return 3 instead of 3.33?

Because the shell performs integer division. It truncates the fractional part. To get a decimal, use bc or awk.

How do I increment a variable in a shell loop?

Use ((i++)) or i=$((i+1)). For example: for ((i=0; i<10; i++)); do echo $i; done.

What is the difference between expr and $(( ))?

expr is an external command that works in all shells, but it is slower and requires escaping * and (. Arithmetic expansion is a shell built-in, faster, and more readable, but only works in POSIX-compliant shells.

Can I use variables in arithmetic expansion?

Yes, but you do not need the dollar sign inside $(( )). For example: a=5; echo $((a + 2)) prints 7. You can also use $a, but it is not necessary.

How do I handle division by zero gracefully?

Check the divisor before dividing. For example: if [ $b -ne 0 ]; then echo $((a / b)); else echo "Cannot divide by zero"; fi.

Related

Formula used
in a | First number | - | 10 | -1000000 | 1000000
in b | Second number | - | 3 | -1000000 | 1000000
out sum | Sum | - | a + b | 2
out product | Product | - | a * b | 2
out quotient | Quotient (a / b) | - | a / b | 2
out remainder | Remainder (a % b) | - | a % b | 2

Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →