I'm looking for a way to neatly show rounded floats of varying decimal lengh.
Example of what I'm looking for:
In: 0.0000000071234%
Out: 0.0000000071%
In: 0.00061231999999%
Out: 0.0061%
In: 0.149999999%
Out: 0.15%
One way to do it would be:
def dynamic_round(num):
zeros = 2
original = num
while num< 0.1:
num*= 10
zeros += 1
return round(original, zeros)
I'm sure however there is a much cleaner way to do the same thing.
Here's a way to do it without a loop:
a = 0.003123
log10 = -int(math.log10(a))
res = round(a, log10+2)
==> 0.0031
This post answers your question with a similar logic
How can I format a decimal to always show 2 decimal places?
but just to clarify
One way would be to use round() function also mentioned in the documentation
built-in functions: round()
>>> round(number[,digits])
here digit refers to the precision after decimal point and is optional as well.
Alternatively, you can also use new format specifications
>>> from math import pi # pi ~ 3.141592653589793
>>> '{0:.2f}'.format(pi)
'3.14'
here the number next to f tells the precision and f refers to float.
Another way to go here is to import numpy
>>>import numpy
>>>a=0.0000327123
>>>res=-int(numpy.log10(a))
>>>round(a,res+2)
>>>0.000033
numpy.log() also, takes an array as an argument, so if you have multiple values you can iterate through the array.
Related
i have a problem in python3
my variable is
i = 31.807
I would transform in this:
i = 31.80
with two numbers after the decimal point and without round even show 0 in end.
Question: how do I round a float in Python to the desired decimal digit?
You can use numpy.round and supply the value to round and the number of significant digits, i.e.
import numpy as np
i = np.round(31.807, 2)
print(i)
the output is going to be 31.81, which differs from you example.
Question: how do I ceil/floor to the desired decimal digit?
Unfortunately numpy.ceil and numpy.floor do not allow for that, so you need to be a bit more crafy:
import numpy as np
i = np.floor(31.807*100)/100
print(i)
the output is now 31.8.
Question: how do I print a number in a specific format?
Here there is no single write way to go, one possibility is:
print("{:.2f}".format(31.8))
Output: 31.80.
I think the solution from this question here: stackoverflow.com/a/37697840/5273907 would solve your problem i.e.:
import math
def truncate(number, digits) -> float:
stepper = 10.0 ** digits
return math.trunc(stepper * number) / stepper
When I test it locally with your example I get:
>>> truncate(31.807, 2)
31.8
We all know that if we want to find the last number of 1182973981273983 which is 3 we simply do this:
>>> print(1182973981273983 % 10)
3
But if I want to get the last number of 2387123.23 I was thinking of doing this:
>>> 2387123.23 % 10 ** (-1 * 2)
0.009999999931681564
But it doesn't work. What is the mathematical way of getting the last number a decimal number.
p.s. String solutions are invalid. We are programmers we need to know how math works.
As people have already pointed out in the comments, this is not possible for floating point numbers; the concept of 'last decimal' simply doesn't apply. See links in comments for more details.
On the other hand, this would work if you were using fixed point arithmetic (i.e. the Decimal type). Then a solution might look like this:
>>> import decimal
>>> d = decimal.Decimal('3.14')
>>> d.as_tuple().digits[-1]
4
I'm trying to take a large integer, ie: 123123123 and format it with 3-digits of precision and commas. Format can add the commas using:
'{:,}'.format(123123123) # '123,123,123'
And specify precision for floating points:
'{0:.2f}'.format(3.141592) # '3.14'
But what if I want to do both?
ie:
'{:,3d}'.format(123123123) # ValueError
I would like to have it return: 123,000,000
There is no way to do this directly. The whole point of Python integers is that they're infinite-precision; if you want to round them, you have to do it explicitly. In fact, when you attempted the obvious, the message in the exception told you this:
>>> '{:,.3d}'.format(123123123)
ValueError: Precision not allowed in integer format specifier
So, your attempt at this is in the right directly… but it's more than a little funky:
'{:,.0f}'.format(round(123123123,-6))
There's no reason to explicitly force the int to a float just so you can print it without any fractional values. Just let it stay an int:
'{:,}'.format(round(123123123, -6))
Besides being simpler, this also means that when you try to one day print a giant integer, it won't give you an OverflowError or lose more digits than you wanted…
In earlier versions of Python (that is, 2.x), where round always returns float no matter what type you give it, you can't do that; you will probably want to write a trivial intround function instead. For example:
def intround(number, ndigits):
return (number + 5 * 10**(-ndigits-1)) // 10**-ndigits * 10**-ndigits
If you know for a fact that you will never have an integer too large to fit losslessly into a float, you can just use int(round(*args)) instead—but really, if you can avoid converting integers to floats, you should.
And, while we're at it, there's no reason to build up a {} string to call the format method on when you can just call the free function:
format(round(123123123, -6), ',')
The 'right' way to do this that is Python version independent (well -- it has to have with so 2.5+) is use the Decimal module:
from __future__ import print_function
import decimal
import sys
if sys.version_info.major<3:
ic=long
else:
ic=int
def ri(i, places=6):
with decimal.localcontext() as lct:
lct.prec=places
n=ic(decimal.Decimal(i,)+decimal.Decimal('0'))
return format(n,',')
print(ri(2**99, 4))
# 633,800,000,000,000,000,000,000,000,000
print(ri(12349159111, 7))
# 12,349,160,000
print(ri(12349111111, 3))
# 12,300,000,000
If you use the round method it is fairly fragile on Python 2:
Python 2:
>>> format(round(12349999999999999,-6),',')
'1.235e+16' # wrong....
It works on Python 3, but this is the way to do it so the rounding is left to right:
def rir(i, places=6):
return format(round(i, places-len(str(i))), ',')
print(rir(2**99, 4))
# 633,800,000,000,000,000,000,000,000,000
print(rir(12349159111, 7))
# 12,349,160,000
With a negative offset for ndigits, round(number[, ndigits]) will round the mantissa of the floating point right to left:
>>> round(123456789,-4)
123456789123460000
Works great on Python 3 with larger numbers:
>>> round(123456789123456789,-8)
123456789100000000
On Python 2, the functionality breaks with larger numbers:
>>> round(123456789,-4)
123460000.0
>>> round(123456789123456789,-4)
1.2345678912346e+17
With the decimal module, it works as expected on Python 2 and Python 3.
Looking to format a output to show a very small number..
a= 6500
b= 3600
c=.000900
d= int((b/a)-c)
print d
Answer comes out to be zero, but looking for the .###### numbers after the .
sorry try this
Looks like you got bitten by integer division in python 2.x.
>>> a= 6500
>>> b= 3600
>>> c=.000900
>>> from __future__ import division
>>> print b/a - c
0.552946153846
There may be two issues with your calculation:
If you're using Python 2, division using / between two integers will always be an integer also. This will discard the fractional part of the calculation, which can be unexpected. One fix for this is to force one of the values to be a float value (e.g. float(b)/a). An alternative is to put at the top of your file from __future__ import division, which tells Python to use the Python 3 semantics for division (you'll only get an integer from integer division if the result is an exact integer).
The second issue seems to be about formatting a floating point value. First you seem to want only the fractional part of the value (not the integer part). Usually the best option is to simply subtract the integer part of the value:
d = someFloatingPointValue()
d_frac = d - int(d)
Next, to get a string to output (where you want several decimal places, but not a huge number of them), you probably want to explore Python's string formatting operations:
d = someFloatingPointValue()
d_to4decimalPlaces = "{:.4f}".format(d)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
python limiting floats to two decimal points
i want to set 39.54484700000000 to 39.54 using python ,
how to get it ,
thanks
If you want to change the actual value, use round as Eli suggested. However for many values and certain versions of Python this will not result be represented as the string "39.54". If you want to just round it to produce a string to display to the user, you can do
>>> print "%.2f" % (39.54484700000000)
39.54
or in newer versions of Python
>>> print("{:.2f}".format(39.54484700000000))
39.54
or with the fstrings
>>> print(f'{39.54484700000000:.2f}')
39.54
Relevant Documentation: String Formatting Operations, Built-in Functions: round
How about round
>>> import decimal
>>> d=decimal.Decimal("39.54484700000000")
>>> round(d,2)
39.54
You can use the quantize method if you're using a Decimal:
In [24]: q = Decimal('0.00')
In [25]: d = Decimal("115.79341800000000")
In [26]: d.quantize(q)
Out[26]: Decimal("115.79")
>>> round(39.54484700000000, 2)
39.54
Note, however, that the result isn't actually 39.54, but 39.53999999999999914734871708787977695465087890625.
Use round:
Return the floating point value x
rounded to n digits after the decimal
point. If n is omitted, it defaults to
zero. The result is a floating point
number.
Values are rounded to the closest
multiple of 10 to the power minus n;
if two multiples are equally close,
rounding is done away from 0
>>> round(39.544847, 2)
39.539999999999999
>>>
Note that since 39.54 isn't exactly represantable with floating points on my PC (x86), the result is an epsilon off. But that makes no difference (and is a whole different issue with many SO questions and answers on it). If you convert it to a string properly, you'll see what you expect:
>>> "%.2f" % round(39.544847, 2)
'39.54'
Eli mentions using the round function -- depending on your requirements, you may want to return a Decimal object instead.
>>> from decimal import Decimal
>>> float_val = 39.54484700000000
>>> decimal_val = Decimal("%.2f" % float_val)
>>> print decimal_val
39.54
Using Decimal objects lets you specify the exact number of decimal places that you want to keep track of, so you avoid ending up with a floating point number that is represented as 39.539999999999999. Specifically, if you are doing financial calculations, you will almost always be advised to stay away from floating-point numbers.
You can't cast floats directly into Decimals, however (the floats are imprecise, and Python can't guess how you want them rounded,) so I will almost always convert them to a rounded string representation first (that's the "%.2f" % float_val -- %.2f means to display only two decimals, and then create a Decimal out of that.