Skip to main content

How to Round Decimal Numbers

• 4 min read
bash math rounding floating-point printf bc

Quick Answer: Round Decimal Numbers in Bash

To round a decimal number to a specific number of places in Bash, use printf "%.2f" "$number" for 2 decimal places. This is the fastest, simplest method and requires no external tools. For more precise control or financial calculations, use bc: echo "scale=2; $number" | bc.

Quick Comparison: Rounding Methods

MethodSpeedPrecisionBest ForLimitations
printfFastestGoodGeneral roundingLimited precision
bcSlowExcellentFinancial mathRequires bc
awkMediumGoodBatch processingRequires awk
TruncationFastN/AFloor operationNo actual rounding

Bottom line: Use printf for speed; use bc for financial calculations where precision matters.


Round decimal numbers to a specific number of decimal places in Bash. Bash doesn’t have native floating-point support, so we use printf, bc, awk, or other tools.

Method 1: Round Using printf (The Standard Approach)

The simplest and fastest method for basic rounding. Printf is a built-in Bash command that formats numbers without spawning external processes:

number=3.14159
printf "%.2f\n" "$number"

# Output: 3.14

Printf is incredibly fast and reliable. The syntax %.Nf where N is the number of decimal places you want. This works for positive and negative numbers, and it performs actual rounding (not truncation).

Round to Different Decimal Places

number=3.14159

# Round to 0 decimal places (integer)
printf "%.0f\n" "$number"    # Output: 3

# Round to 1 decimal place
printf "%.1f\n" "$number"    # Output: 3.1

# Round to 2 decimal places
printf "%.2f\n" "$number"    # Output: 3.14

# Round to 4 decimal places
printf "%.4f\n" "$number"    # Output: 3.1416

When to Use printf

Use this method when:

  • You need the fastest rounding
  • You want a pure Bash solution (no dependencies)
  • Precision to 15 decimal places is sufficient
  • You’re rounding numbers for display purposes
  • You’re processing many numbers in a loop

Avoid it when:

  • You need financial-grade precision (use bc instead)
  • You’re doing complex calculations requiring 20+ decimal places
  • You need to preserve trailing zeros consistently

Method 2: Using bc (Binary Calculator)

For more control and precision, use bc which handles arbitrary precision arithmetic:

number=3.14159

# Round to 2 decimal places
echo "scale=2; $number" | bc

# Output: 3.14

The scale variable controls decimal precision. This is essential for financial calculations where truncation errors matter.

When to Use bc

Use bc when:

  • You need financial-grade precision
  • You’re doing calculations that accumulate rounding errors
  • You need exact control over rounding behavior
  • You’re handling currency or accounting
  • You need more than 15 decimal places

Avoid bc when:

  • You’re processing millions of numbers (slow)
  • You just need basic display rounding (use printf instead)
  • You can’t depend on bc being installed

Method 3: Function for Flexible Rounding

Create a reusable function that wraps printf for convenient use:

#!/bin/bash

round() {
  local number="$1"
  local decimals="${2:-0}"

  printf "%.${decimals}f\n" "$number"
}

# Usage
round 3.14159 2     # Output: 3.14
round 2.5 0         # Output: 3 (rounds to nearest)
round 1.2345 3      # Output: 1.235

This function makes your code cleaner and easier to read. You can pass the number and desired decimal places as arguments.

Method 4: Rounding with bc Function

For better precision in calculations, wrap bc in a function:

#!/bin/bash

round_bc() {
  local number="$1"
  local decimals="${2:-0}"

  echo "scale=$decimals; $number + 0.5 * 10^(-$decimals)" | bc
}

# Usage
round_bc 3.14159 2
round_bc 2.4999 2

This adds proper mathematical rounding using bc’s scale parameter.

Method 5: Round Up (Ceiling)

To always round up to the next value:

#!/bin/bash

# Simple ceiling using awk
round_ceil() {
  local number="$1"
  local decimals="${2:-0}"

  awk -v num="$number" -v dec="$decimals" 'BEGIN { printf "%.${decimals}f\n", ceil(num * 10^dec) / 10^dec }'
}

round_ceil 3.141 2    # 3.15 (rounded up)

Method 6: Round Down (Floor)

To always round down (truncate):

#!/bin/bash

# Round down using bc
round_floor() {
  local number="$1"
  local decimals="${2:-0}"

  # Remove digits beyond decimal places
  echo "scale=$decimals; $(echo "$number * 10^$decimals" | bc) / 10^$decimals" | bc
}

round_floor 3.149 2    # Output: 3.14

Practical Example: Financial Rounding

#!/bin/bash

# File: calculate_total.sh

round_to_cents() {
  printf "%.2f\n" "$1"
}

# Sales tax calculation
item_price=19.99
tax_rate=0.0825

tax_amount=$(echo "$item_price * $tax_rate" | bc)
tax_rounded=$(round_to_cents "$tax_amount")

total=$(echo "$item_price + $tax_rounded" | bc)
total_rounded=$(round_to_cents "$total")

echo "Item Price: \$$(round_to_cents $item_price)"
echo "Tax Rate: ${tax_rate}%"
echo "Tax Amount: \$${tax_rounded}"
echo "Total: \$${total_rounded}"

Output:

Item Price: $19.99
Tax Rate: 0.0825%
Tax Amount: $1.65
Total: $21.64

Rounding in Calculations

#!/bin/bash

# Average calculation with rounding
value1=10.567
value2=20.432
value3=15.891

average=$(echo "scale=10; ($value1 + $value2 + $value3) / 3" | bc)
average_rounded=$(printf "%.2f\n" "$average")

echo "Average: $average_rounded"

Output:

Average: 15.63

Rounding Large Dataset

#!/bin/bash

# File: round_values.sh

input_file="$1"
decimals="${2:-2}"

if [ ! -f "$input_file" ]; then
  echo "Usage: $0 <input_file> [decimals]"
  exit 1
fi

echo "Rounding values to $decimals decimal places..."
echo ""

while IFS= read -r line; do
  rounded=$(printf "%.${decimals}f\n" "$line")
  echo "$rounded"
done < "$input_file"

Test file (values.txt):

3.14159
2.71828
1.41421
0.57721

Usage:

$ chmod +x round_values.sh
$ ./round_values.sh values.txt 2

Output:

Rounding values to 2 decimal places...

3.14
2.72
1.41
0.58

Using awk for Rounding

# Round in awk
awk '{printf "%.2f\n", $1}' values.txt

# Round with conditional
awk '$1 > 5 {printf "%.2f\n", $1}' values.txt

# Round and multiply
awk '{printf "%.2f\n", $1 * 1.1}' values.txt

Batch Processing with Rounding

#!/bin/bash

# Process CSV file, rounding price column

input="prices.csv"
output="prices_rounded.csv"

while IFS=',' read -r product price; do
  rounded_price=$(printf "%.2f\n" "$price")
  echo "$product,$rounded_price" >> "$output"
done < "$input"

echo "Output written to $output"

Performance Comparison

MethodSpeedPrecisionBest For
printfFastestGoodSimple rounding
bcSlowExcellentFinancial calculations
awkMediumGoodBatch processing

Common Mistakes

  1. Rounding in wrong order - do calculations first, then round
  2. Confusing precision with decimals - 2.0 and 2.00 display differently
  3. Banker’s rounding vs traditional - printf may round differently than expected
  4. Using printf for large numbers - may lose precision
  5. Not handling negative numbers - test with negatives

Rounding Examples

#!/bin/bash

test_values=(3.14159 2.5 1.999 0.1 -3.14159)
decimals=2

for value in "${test_values[@]}"; do
  rounded=$(printf "%.${decimals}f\n" "$value")
  echo "$value → $rounded"
done

Output:

3.14159 → 3.14
2.5 → 2.50
1.999 → 2.00
0.1 → 0.10
-3.14159 → -3.14

Quick Reference

# Printf rounding (fastest)
printf "%.2f\n" 3.14159          # 3.14

# bc rounding (most precise)
echo "scale=2; 3.14159" | bc     # 3.14

# Function call
round() { printf "%.${2:-0}f\n" "$1"; }
round 3.14159 2                  # 3.14

# Rounding in arithmetic
value=$(printf "%.2f\n" $(echo "10 / 3" | bc -l))
echo $value                       # 3.33

Summary

Rounding in Bash is straightforward with printf for basic needs, or bc for precise financial calculations. Use printf as your default—it’s fast and sufficient for most cases. Switch to bc only when precision really matters. Always perform rounding as the final step in calculations to maintain accuracy throughout your computations.