How do you control significant figures in python?

  1. HowTo
  2. Python How-To's
  3. Round to Significant Digits in Python

Created: September-12, 2021 | Updated: October-12, 2021

  1. Use the round() Function to Round a Number to the Given Significant Digit in Python
  2. Use the math Module to Round a Number to the Given Significant Digit in Python
  3. Use String Formatting to Round a Number to the Given Significant Digit in Python
  4. Use the sigfig Module to Round a Number to the Given Significant Digit in Python

Rounding the number means replacing a number with an approximate value that is close to it. We can also round numbers to the required significant figure.

In this article, we will round a number to a specific significant digit in Python.

Use the round() Function to Round a Number to the Given Significant Digit in Python

The round() function rounds the given floating values to the nearest integer or specified decimal position.

We can use a negative number to round the integer to the significant floor value by assigning it to the round() function. This negative number to be specified depends on the required significant digits.

For example, if we wish to round to one significant digit, we specify the value as (1-total digits) in the round() function.

See the following code.

x = round(1342, -3)
print(x)

Output:

1000

Use the math Module to Round a Number to the Given Significant Digit in Python

This method is an improvement on the previously discussed function. We can create a simple user-defined function to make this more convenient. We won’t have to specify the negative number in this method’s round() function. We will replace this using a combination of the math.floor() function and the math.log10() function.

See the code below.

from math import log10 , floor
def round_it(x, sig):
    return round(x, sig-int(floor(log10(abs(x))))-1)

print(round_it(1324,1))

Output:

1000

Use String Formatting to Round a Number to the Given Significant Digit in Python

In Python, the %g specifier in string formats a float rounded to a specified significant figure. If the magnitude of the final number is huge, then it shows it in scientific notation.

This method returns a string. So, we have to convert the string number back to a float or integer value after formatting it.

For example,

x = float('%.1g' % 1324)
print(x)

Output:

1000.0

Use the sigfig Module to Round a Number to the Given Significant Digit in Python

The sigfig module is the best fit for rounding the numbers to a significant digit as it minimizes the hassle of creating a user-defined function and simplifies the code.

We can specify the number of significant digits in this module’s round() function.

See the following example.

from sigfig import round
print(round(1324, sigfigs = 1))

Output:

1000

  • 1 Rounding Off to a Whole Number
    • 1.1 Rounding Down
    • 1.2 Rounding Up
    • 1.3 Rounding Towards Zero
    • 1.4 Rounding Away from Zero
  • 2 Rounding Off to a Number of Decimal Places
    • 2.1 Rounding Using String Formatting
  • 3 Rounding Off to a Number of Significant Figures
    • 3.1 Customising Sig Fig Notation
  • 4 Rounding Using Engineering Notation
    • 4.1 Customising Engineering Notation

⇦ Back

Rounding Off to a Whole Number

Python has a built-in function round() that will, as the name suggests, round a number off:

unrounded = 5.99
rounded = round(unrounded)

print(rounded)
## 6

Note that, by default, this uses the round half to even rule for tie-breaking multiples of 0.5. In other words, any number that ends in “.5” gets rounded to the nearest EVEN whole number:

# 2.5 gets rounded DOWN
print(round(2.5))
## 2
# 3.5 gets rounded UP
print(round(3.5))
## 4

This is true even for negative numbers:

print(round(-2.5))
## -2

This method of rounding off is known as statistician’s rounding and avoids both a positive/negative bias and a bias towards/away from zero

Rounding Down

The built-in math library contains the floor() function that will round numbers ‘towards the floor’ (ie towards negative infinity):

import math

negative_example = math.floor(-2.9)
positive_example = math.floor(2.9)

print(negative_example, positive_example, sep=', ')
## -3, 2

Rounding Up

The complement to floor() is ceil() which will round numbers ‘towards the ceiling’ (ie towards positive infinity):

negative_example = math.ceil(-2.9)
positive_example = math.ceil(2.9)

print(negative_example, positive_example, sep=', ')
## -2, 3

Rounding Towards Zero

The trunc() function truncates a number, which means that it throws away the part after the decimal point. This is equivalent to rounding towards zero:

negative_example = math.trunc(-2.9)
positive_example = math.trunc(2.9)

print(negative_example, positive_example, sep=', ')
## -2, 2

Rounding Away from Zero

There is no single function to do this in math (not even in numpy)! However, here’s a quick custom function you can use:

def round_away_from_zero(x):
    """Round a number x away from 0."""
    return math.ceil(abs(x)) * math.copysign(1, x)


negative_example = round_away_from_zero(-2.9)
positive_example = round_away_from_zero(2.9)

print(negative_example, positive_example, sep=', ')
## -3.0, 3.0

The abs() function takes the absolute value of the un-rounded number (ie makes it positive if it’s negative), rounds it up with ceil() then multiplies that answer by either -1 or 1 using the copysign() function to copy the sign of the original number.

Rounding Off to a Number of Decimal Places

The round() function can take a second argument, namely the number of decimal places you want to round off to:

unrounded = 6.283185
rounded = round(unrounded, 3)

print(rounded)
## 6.283

Again, this uses statistician’s rounding:

# Round DOWN to 6.28318
print(round(6.283185, 5))
## 6.28318

Rounding Using String Formatting

Another method for rounding off is to use the .xf notation with formatted strings (usually these will be ‘f-strings’ - see this page for more info - but you can also use this notation with the older .format() method or %-sign notation). .xf will round a floating-point number off to x places after the decimal point and it can be used with f-strings as follows:

unrounded = 6.283185
rounded = f'The number rounded to 3 decimal places is: {unrounded:.3f}'

print(rounded)
## The number rounded to 3 decimal places is: 6.283

Note that the result is a string not a number! So you can’t do any further calculation with it when using this method.

Rounding Off to a Number of Significant Figures

Instead of rounding off to a certain number of decimal places we often want to round off to a certain number of significant figures - digits excluding leading zeroes. A useful library that will do this is sigfig which can be installed from the terminal with:

# If you have a version of Python that isn't 3.9 use those version numbers instead
python3.9 -m pip install sigfig

This includes a new implementation of the round() function that overwrites the built-in one. It can round off to a given number of decimal places using the decimals keyword argument like so:

import sigfig

unrounded = 1.2345
rounded = sigfig.round(unrounded, decimals=3)

print(f'{1.2345} becomes {rounded}')
## 1.2345 becomes 1.235

Note that this function rounds half away from zero, also known as commercial rounding: 1.2345 gets rounded to 1.235 as opposed to statistician’s rounding which would make it 1.234

This implementation of round() can also round off to a given number of significant figures via the sigfigs keyword argument:

unrounded = 1.2345
rounded = sigfig.round(unrounded, sigfigs=3)

print(f'{1.2345} becomes {rounded}')
## 1.2345 becomes 1.23

Note that exponential notation is preserved unless you convert to a string before invoking the function:

unrounded = 1.2345e-7
exponential = sigfig.round(unrounded, sigfigs=3)
floating = sigfig.round(str(unrounded), sigfigs=3)

print(f'{1.2345e-7} becomes {exponential} or {floating}')
## 1.2345e-07 becomes 1.23e-07 or 0.000000123

This function can also incorporate uncertainty using the uncertainty keyword:

unrounded = 1.2345
rounded = sigfig.round(unrounded, uncertainty=0.0002)

print(f'{1.2345} becomes {rounded}')
## 1.2345 becomes 1.2345 ± 0.0002

And, finally, it can use different representations of uncertainty:

# Estimate Newton's gravitational constant
print('G =', sigfig.round('6.67430', '0.00015', format='Drake'), '×10^−11 m3⋅kg−1⋅s−2')
## G = 6.674 30(15) ×10^−11 m3⋅kg−1⋅s−2

Customising Sig Fig Notation

If you are absolutely set on using statistician’s rounding (or if you want to make any other modifications to how the sigfig package does its rounding), or if you only want to use built-in packages instead of relying on external dependencies, you can re-create the function yourself. This has been done below:

from decimal import Decimal, getcontext


def round_to_sig_figs(x, sigfigs):
    """Round a number off to a given number of significant figures."""
    # A special case is if the number is 0
    if float(x) == 0.0:
        output = '0' * sigfigs
        # Insert a decimal point
        output = output[0] + '.' + output[1:]

        return output

    # A special case is if the number is 'nan'
    if np.isnan(x):

        return 'None'

    # Set the precision
    getcontext().prec = sigfigs
    rounded = Decimal(x)
    # The precision only kicks in when an arithmetic operation is performed
    rounded = rounded * 1
    # Remove scientific notation
    # (if the order of magnitude of the number is larger than the number of
    # significant figures, the number will have been converted to scientific
    # notation)
    rounded = float(rounded)
    # Convert to string
    output = str(rounded)

    # Count the number of significant figures
    sigfigs_now = len(output.replace('-', '').replace('.', '').lstrip('0'))

    # Remove trailing zero if one exists and it is not necessary
    if ((sigfigs_now > sigfigs) and (output.endswith('.0'))):
        output = output.removesuffix('.0')

    # Add trailing zeroes if necessary
    if sigfigs_now < sigfigs:
        discrepancy = sigfigs - sigfigs_now
        # Append a decimal point if necessary
        if '.' not in output:
            output = output + '.'
        # Add trailing zeroes
        output = output + '0' * discrepancy

    return output

Let’s test it:

unrounded = 1.2345
rounded = round_to_sig_figs(unrounded, 4)

print(f'{1.2345} becomes {rounded}')
## 1.2345 becomes 1.234

Rounding Using Engineering Notation

Another useful library to have is engineering_notation. It can be installed from the terminal with:

# If you have a version of Python that isn't 3.9 use those version numbers instead
python3.9 -m pip install engineering_notation

This library contains the EngNumber() function which converts a number into ‘engineering notation’ (ie it represents it as a multiple of \(10^x\) or of \(1/10^x\) where \(x\) is a multiple of 3) using the usual SI units. It then rounds off to a given precision (number of decimal place; 2 by default) or to a given level of significance:

from engineering_notation import EngNumber

# Represent a large number in engineering notation with a unit
# Use default rounding (to 2 decimal places)
raw = 12345
formatted = EngNumber(raw)

print(f'{raw} becomes {formatted}')
## 12345 becomes 12.34k
# Represent a small number in engineering notation with a unit
# Round to 1 decimal place
raw = 0.012345
formatted = EngNumber(raw, precision=1)

print(f'{raw} becomes {formatted}')
## 0.012345 becomes 12.3m
# Represent a number in engineering notation
# Round to 4 significant figures
raw = 6.283185
formatted = EngNumber(raw, significant=4)

print(f'{raw} becomes {formatted}')
## 6.283185 becomes 6.283

Customising Engineering Notation

If you want to tweak the output of EngNumber() you can copy the function’s source code from GitHub and edit it yourself. Here’s an example of exactly that: the EngNumber() function re-moulded into a new function round_engineering() that represents the output in a variant of exponential notation:

from decimal import Decimal


def round_engineering(value, precision=2, significant=0):
    """
    Round and convert to an exponential format that is a multiple of 3.

    :return: A string representing the engineering number
    """
    number = Decimal(str(value))

    # Since the Decimal class only really converts numbers that are very small
    # into engineering notation we will simply make all numbers small numbers.
    # We can then take advantage of the Decimal class
    num_str = number * Decimal('10e-25')
    num_str = num_str.to_eng_string().lower()

    base, exponent = num_str.split('e')

    if significant > 0:
        if abs(Decimal(base)) >= 100.0:
            base = str(round(Decimal(base), significant - 3))
        elif abs(Decimal(base)) >= 10.0:
            base = str(round(Decimal(base), significant - 2))
        else:
            base = str(round(Decimal(base), significant - 1))
    else:
        base = str(round(Decimal(base), precision))

    if 'e' in base.lower():
        base = str(int(Decimal(base)))

    # Remove trailing decimals
    # https://stackoverflow.com/questions/3410976/how-to-round-a-number-to-significant-figures-in-python
    # https://stackoverflow.com/questions/11227620/drop-trailing-zeros-from-decimal
    if '.' in base:
        base = base.rstrip('.')

    # Remove trailing .00 in precision 2
    if precision == 2 and significant == 0:
        if '.00' in base:
            base = base[:-3]

    # Scale the exponent back to normal
    exponent = str(int(exponent) + 24)
    # Format the exponent
    if exponent == '0':
        exponent_str = ''
    else:
        exponent_str = '×10^' + exponent

    return base + exponent_str

Here’s how it’s used:

numbers = [
    1,
    12,
    123,
    1234,
    12345,
    123456,
    0.1234,
    1.234,
    12.34,
    123.4,
    1234,
]
for number in numbers:
    print(f'{number:>7} becomes {round_engineering(number, significant=3)}')
##       1 becomes 1.00
##      12 becomes 12.0
##     123 becomes 123
##    1234 becomes 1.23×10^3
##   12345 becomes 12.3×10^3
##  123456 becomes 123×10^3
##  0.1234 becomes 123×10^-3
##   1.234 becomes 1.23
##   12.34 becomes 12.3
##   123.4 becomes 123
##    1234 becomes 1.23×10^3

⇦ Back

How do you format sig figs in Python?

This is easily achievable using Python's exponential format specifier: %e or %E . For example if you want to display the number 1.23 to 4 significant digits you can do "%. 3E" % (1.23) and Python will correctly print 1.230E+00 .

How do you use .2f in Python?

2f is a placeholder for floating point number. So %d is replaced by the first value of the tuple i.e 12 and %. 2f is replaced by second value i.e 150.87612 . ... Python String Formatting..

How do you handle significant figures?

Count the number of significant figures in the decimal portion ONLY of each number in the problem. Add or subtract in the normal fashion. Your final answer may have no more significant figures to the right of the decimal than the LEAST number of significant figures in any number in the problem.

How do you control a float in Python?

Therefore, in this tutorial, you learned about the following methods to limit a given floating-point value to two decimal points in Python:.
Method 1: Using round() function..
Method 2: Using The format() Function..
Method 3: By Using % Formatting..
Method 4: By using f-strings..
Method 5: Using quantize() with Decimal..