I need to round a float to be displayed in a UI. E.g, to one significant figure:
1234 -> 1000
0.12 -> 0.1
0.012 -> 0.01
0.062 -> 0.06
6253 -> 6000
1999 -> 2000
Is there a nice way to do this using the Python library, or do I have to write it myself?
I need to round a float to be displayed in a UI. E.g, to one significant figure:
1234 -> 1000
0.12 -> 0.1
0.012 -> 0.01
0.062 -> 0.06
6253 -> 6000
1999 -> 2000
Is there a nice way to do this using the Python library, or do I have to write it myself?
I can't think of anything that would be able to handle this out of the box. But it's fairly well handled for floating point numbers.
>>> round(1.2322, 2)
1.23
Integers are trickier. They're not stored as base 10 in memory, so significant places isn't a natural thing to do. It's fairly trivial to implement once they're a string though.
Or for integers:
>>> def intround(n, sigfigs):
... n = str(n)
... return n[:sigfigs] + ('0' * (len(n)-(sigfigs)))
>>> intround(1234, 1)
'1000'
>>> intround(1234, 2)
If you would like to create a function that handles any number, my preference would be to convert them both to strings and look for a decimal place to decide what to do:
>>> def roundall1(n, sigfigs):
... n = str(n)
... try:
... sigfigs = n.index('.')
... except ValueError:
... pass
... return intround(n, sigfigs)
Another option is to check for type. This will be far less flexible, and will probably not play nicely with other numbers such as Decimal objects:
>>> def roundall2(n, sigfigs):
... if type(n) is int: return intround(n, sigfigs)
... else: return round(n, sigfigs)
Focusing on "I need to round a float to be displayed in a UI", string formatting is your friend.
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(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.
%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'
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(x)))-1)
...
>>> round_sig(0.0232)
0.023
>>> round_sig(0.0232, 1)
0.02
>>> round_sig(1234243, 3)
1230000.0