You can use negative numbers to round integers:
>>> round[1234, -3]
1000.0
Thus if you need only most significant digit:
>>> from math import log10, floor
>>> def round_to_1[x]:
... return round[x, -int[floor[log10[abs[x]]]]]
...
>>> round_to_1[0.0232]
0.02
>>> round_to_1[1234243]
1000000.0
>>> round_to_1[13]
10.0
>>> round_to_1[4]
4.0
>>> round_to_1[19]
20.0
You'll probably have to take care of turning float to integer if it's bigger than 1.
answered Aug 5, 2010 at 2:57
13
%g in string formatting will format a float rounded to some number of significant figures. It will sometimes use 'e' scientific notation, so convert the rounded string back to a float then through %s string formatting.
>>> '%s' % float['%.1g' % 1234]
'1000'
>>> '%s' % float['%.1g' % 0.12]
'0.1'
>>> '%s' % float['%.1g' % 0.012]
'0.01'
>>> '%s' % float['%.1g' % 0.062]
'0.06'
>>> '%s' % float['%.1g' % 6253]
'6000.0'
>>> '%s' % float['%.1g' % 1999]
'2000.0'
answered Aug 5, 2010 at 4:24
Peter GrahamPeter Graham
10.9k7 gold badges38 silver badges42 bronze badges
10
If you want to have other than 1 significant decimal [otherwise the same as Evgeny]:
>>> from math import log10, floor
>>> def round_sig[x, sig=2]:
... return round[x, sig-int[floor[log10[abs[x]]]]-1]
...
>>> round_sig[0.0232]
0.023
>>> round_sig[0.0232, 1]
0.02
>>> round_sig[1234243, 3]
1230000.0
Stephen Rauch♦
45.7k30 gold badges105 silver badges126 bronze badges
answered Aug 5, 2010 at 9:49
indgarindgar
6794 silver badges2 bronze badges
8
f'{float[f"{i:.1g}"]:g}'
# Or with Python >> sig_dig[1234243, 3]
>>> sig_dig[243.3576, 5]
1230.0
243.36
answered Mar 26, 2020 at 21:29
LetzerWilleLetzerWille
5,2214 gold badges22 silver badges26 bronze badges
4
Most of these answers involve the math, decimal and/or numpy imports or output values as strings. Here is a simple solution in base python that handles both large and small numbers and outputs a float:
def sig_fig_round[number, digits=3]:
power = "{:e}".format[number].split['e'][1]
return round[number, -[int[power] - digits]]
answered Dec 16, 2020 at 18:23
A simple variant using the standard decimal library
from decimal import Decimal
def to_significant_figures[v: float, n_figures: int] -> str:
d = Decimal[v]
d = d.quantize[Decimal[[0, [], d.adjusted[] - n_figures + 1]]]
return str[d.quantize[Decimal[1]] if d == d.to_integral[] else d.normalize[]]
Testing it
>>> to_significant_figures[1.234567, 3]
'1.23'
>>> to_significant_figures[1234567, 3]
'1230000'
>>> to_significant_figures[1.23, 7]
'1.23'
>>> to_significant_figures[123, 7]
'123'
answered Sep 4, 2021 at 21:47
This function takes both positive and negative numbers and does the proper significant digit rounding.
from math import floor
def significant_arithmetic_rounding[n, d]:
'''
This function takes a floating point number and the no. of significant digit d, perform significant digits
arithmetic rounding and returns the floating point number after rounding
'''
if n == 0:
return 0
else:
# Checking whether the no. is negative or positive. If it is negative we will take the absolute value of it and proceed
neg_flag = 0
if n < 0:
neg_flag = 1
n = abs[n]
n1 = n
# Counting the no. of digits to the left of the decimal point in the no.
ld = 0
while[n1 >= 1]:
n1 /= 10
ld += 1
n1 = n
# Counting the no. of zeros to the right of the decimal point and before the first significant digit in the no.
z = 0
if ld == 0:
while[n1 >> significant_arithmetic_rounding[1234, 3]
1230.0
>>> significant_arithmetic_rounding[123.4, 3]
123.0
>>> significant_arithmetic_rounding[0.0012345, 3]
0.00123
>>> significant_arithmetic_rounding[-0.12345, 3]
-0.123
>>> significant_arithmetic_rounding[-30.15345, 3]
-30.2
answered Dec 7, 2021 at 15:08
Easier to know an answer works for your needs when it includes examples. The following is built on previous solutions, but offers a more general function which can round to 1, 2, 3, 4, or any number of significant digits.
import math
# Given x as float or decimal, returns as string a number rounded to "sig" significant digts
# Return as string in order to control significant digits, could be a float or decimal
def round_sig[x, sig=2]:
r = round[x, sig-int[math.floor[math.log10[abs[x]]]]-1]
floatsig = "%." + str[sig] + "g"
return "%d"%r if abs[r] >= 10**[sig-1] else '%s'%float[floatsig % r]
>>> a = [1234, 123.4, 12.34, 1.234, 0.1234, 0.01234, 0.25, 1999, -3.14, -48.01, 0.75]
>>> [print[i, "->", round_sig[i,1], round_sig[i], round_sig[i,3], round_sig[i,4]] for i in a]
1234 -> 1000 1200 1230 1234
123.4 -> 100 120 123 123.4
12.34 -> 10 12 12.3 12.34
1.234 -> 1 1.2 1.23 1.234
0.1234 -> 0.1 0.12 0.123 0.1234
0.01234 -> 0.01 0.012 0.0123 0.01234
0.25 -> 0.2 0.25 0.25 0.25
1999 -> 2000 2000 2000 1999
-3.14 -> -3 -3.1 -3.14 -3.14
-48.01 -> -50 -48 -48.0 -48.01
0.75 -> 0.8 0.75 0.75 0.75
answered Apr 22 at 20:01
chadnchadn
2491 gold badge2 silver badges7 bronze badges
in very cases, the number of significant is depend on to the evaluated process, e.g. error. I wrote the some codes which returns a number according to it's error [or with some desired digits] and also in string form [which doesn't eliminate right side significant zeros]
import numpy as np
def Sig_Digit[x, *N,]:
if abs[x] < 1.0e-15:
return[1]
N = 1 if N ==[] else N[0]
k = int[round[abs[N]-1]]-int[np.floor[np.log10[abs[x]]]]
return[k];
def Sig_Format[x, *Error,]:
if abs[x] < 1.0e-15:
return['{}']
Error = 1 if Error ==[] else abs[Error[0]]
k = int[np.floor[np.log10[abs[x]]]]
z = x/10**k
k = -Sig_Digit[Error, 1]
m = 10**k
y = round[x*m]/m
if k < 0:
k = abs[k]
if z >= 9.5:
FMT = '{:'+'{}'.format[1+k]+'.'+'{}'.format[k-1]+'f}'
else:
FMT = '{:'+'{}'.format[2+k]+'.'+'{}'.format[k]+'f}'
elif k == 0:
if z >= 9.5:
FMT = '{:'+'{}'.format[1+k]+'.0e}'
else:
FMT = '{:'+'{}'.format[2+k]+'.0f}'
else:
FMT = '{:'+'{}'.format[2+k]+'.'+'{}'.format[k]+'e}'
return[FMT]
def Sci_Format[x, *N]:
if abs[x] < 1.0e-15:
return['{}']
N = 1 if N ==[] else N[0]
N = int[round[abs[N]-1]]
y = abs[x]
k = int[np.floor[np.log10[y]]]
z = x/10**k
k = k-N
m = 10**k
y = round[x/m]*m
if k < 0:
k = abs[k]
if z >= 9.5:
FMT = '{:'+'{}'.format[1+k]+'.'+'{}'.format[k-1]+'f}'
else:
FMT = '{:'+'{}'.format[2+k]+'.'+'{}'.format[k]+'f}'
elif k == 0:
if z >= 9.5:
FMT = '{:'+'{}'.format[1+k]+'.0e}'
else:
FMT = '{:'+'{}'.format[2+k]+'.0f}'
else:
FMT = '{:'+'{}'.format[2+N]+'.'+'{}'.format[N]+'e}'
return[FMT]
def Significant[x, *Error]:
N = 0 if Error ==[] else Sig_Digit[abs[Error[0]], 1]
m = 10**N
y = round[x*m]/m
return[y]
def Scientific[x, *N]:
m = 10**Sig_Digit[x, *N]
y = round[x*m]/m
return[y]
def Scientific_Str[x, *N,]:
FMT = Sci_Format[x, *N]
return[FMT.format[x]]
def Significant_Str[x, *Error,]:
FMT = Sig_Format[x, *Error]
return[FMT.format[x]]
test code:
X = [19.03345607, 12.075, 360.108321344, 4325.007605343]
Error = [1.245, 0.1245, 0.0563, 0.01245, 0.001563, 0.0004603]
for x in X:
for error in Error:
print[x,'+/-',error, end=' \t==> ']
print[' [',Significant_Str[x, error], '+/-', Scientific_Str[error],']']
print out:
19.03345607 +/- 1.245 ==> [ 19 +/- 1 ]
19.03345607 +/- 0.1245 ==> [ 19.0 +/- 0.1 ]
19.03345607 +/- 0.0563 ==> [ 19.03 +/- 0.06 ]
19.03345607 +/- 0.01245 ==> [ 19.03 +/- 0.01 ]
19.03345607 +/- 0.001563 ==> [ 19.033 +/- 0.002 ]
19.03345607 +/- 0.0004603 ==> [ 19.0335 +/- 0.0005 ]
12.075 +/- 1.245 ==> [ 12 +/- 1 ]
12.075 +/- 0.1245 ==> [ 12.1 +/- 0.1 ]
12.075 +/- 0.0563 ==> [ 12.07 +/- 0.06 ]
12.075 +/- 0.01245 ==> [ 12.07 +/- 0.01 ]
12.075 +/- 0.001563 ==> [ 12.075 +/- 0.002 ]
12.075 +/- 0.0004603 ==> [ 12.0750 +/- 0.0005 ]
360.108321344 +/- 1.245 ==> [ 360 +/- 1 ]
360.108321344 +/- 0.1245 ==> [ 360.1 +/- 0.1 ]
360.108321344 +/- 0.0563 ==> [ 360.11 +/- 0.06 ]
360.108321344 +/- 0.01245 ==> [ 360.11 +/- 0.01 ]
360.108321344 +/- 0.001563 ==> [ 360.108 +/- 0.002 ]
360.108321344 +/- 0.0004603 ==> [ 360.1083 +/- 0.0005 ]
4325.007605343 +/- 1.245 ==> [ 4325 +/- 1 ]
4325.007605343 +/- 0.1245 ==> [ 4325.0 +/- 0.1 ]
4325.007605343 +/- 0.0563 ==> [ 4325.01 +/- 0.06 ]
4325.007605343 +/- 0.01245 ==> [ 4325.01 +/- 0.01 ]
4325.007605343 +/- 0.001563 ==> [ 4325.008 +/- 0.002 ]
4325.007605343 +/- 0.0004603 ==> [ 4325.0076 +/- 0.0005 ]
answered Sep 17 at 16:11