Round to significant figures in python

11,503

Solution 1

I assume you want to round to 6 significant figures. If you want to round ints, you can use

def round_sf(number, significant):
    return round(number, significant - len(str(number)))

print(round_sf(4252017622, 6))

Result:

4252020000

Solution 2

The accepted answer has limitations and does not produce technically correct significant figures in the general case.

numpy.format_float_positional supports the desired behaviour directly. The following fragment returns the float x formatted to 4 significant figures, with scientific notation suppressed.

import numpy as np
x=12345.6
np.format_float_positional(x, precision=4, unique=False, fractional=False, trim='k')
> 12340.

Solution 3

To expand upon Autumn's answer, the reason that the accepted answer fails in the general case is that round is rounding to decimal places and not (necessarily) to significant figures.

The following function addresses the case when there are significant figures both before and after the decimal place:

import math
def round_to_nsf(number, nsf=6):
    integer_part = math.floor(number)
    return round(number, nsf - len(str(integer_part)))

although it doesn't address the case for numbers like 0.0000012345678, which rounded to 6 s.f. should be 0.00000123457.

The following code almost works - but is very inefficient, risks stack overflow through its use of recursion and won't always return the correct answer due to the fact that computers use binary arithmetic instead of decimal:

def round_to_nsf(number, nsf=6):
    integer_part = math.floor(number)
    if integer_part > 0:
        return round(number, nsf - len(str(integer_part)))
    else:
        return round_to_nsf(10 * number, nsf) / 10

But I think that the else clause could be modified by transforming the number into a string, using the main function in a single recursive step, then constructing the output from strings in order to obtain a non-recurring decimal.

Share:
11,503

Related videos on Youtube

golu
Author by

golu

Updated on June 04, 2022

Comments

  • golu
    golu almost 2 years

    I want to round like this 42949672 -> 42949700, 2147483647 -> 2147480000, 4252017622 -> 4252020000 etc.

    I tried to use following , but only works for the first one. How can I make a more general one? thanks

    round(42949672, -2)
    
    • BasedRebel
      BasedRebel almost 7 years
      round(2147483647, -4) gives 2147480000 as desired. You need to tell it how many digits places to round to.
    • golu
      golu almost 7 years
      yes, but round(42949672, -4) doesn't give 42949700. I guess I need to digit places math myself