Python 3.0+ setting to max 4 decimal and rounding - python

So I have an assignment to match an expected output: 34.7381. But I am getting 34.73809999999999. I realize that it is just a rounded number with only 4 decimal places but I have no clue how to that in a short step.
I could brute force it and check for the placement of the decimal point, checking how many characters are after it, eliminating all of them and doing the rounding myself. But that seems rather complicated and stupid for something so simple.
Thanks you for your help!

Have you tried round function?
a = 34.73809999999999
print round(a, 4)
>>> 34.7381

You can use string formatting:
>>> '{:0.4f}'.format(34.7381)
'34.7381'
>>> '{:0.4f}'.format(34.73809999999999)
'34.7381'

Don't worry about it, and just specify the precision you want in your printing:
>>> print('{:.4f}'.format(34.73809999999999))
34.7381

Related

How to round 0.055 to 0.06 in Python?

Result of a simple division -34.11/2 returns -17.055 Is there a python function that would return round up decimal? I am expecting to see -17.06
And yes I checked these answers, but neither can answer this question:
Round up to Second Decimal Place in Python
How to round to nearest decimal in Python
Increment a Python floating point value by the smallest possible amount
Python round to nearest 0.25
Any help would be greatly appreciated.
Thanks!
This is a floating point limitation; get around it by using decimal.Decimal.
>>> from decimal import Decimal
>>> Decimal(-34.11/2) # See? Not quite the value you thought.
Decimal('-17.05499999999999971578290569595992565155029296875')
>>> Decimal(-34.11) / Decimal(2) # This doesn't quite work either, because -34.11 is already a little bit off.
Decimal('-17.05499999999999971578290570')
>>> Decimal("-34.11") / Decimal("2")
Decimal('-17.055')
>>> round(Decimal("-34.11") / Decimal("2"), 2)
Decimal('-17.06')

How to force the number of digits in python [duplicate]

I need to print or convert a float number to 15 decimal place string even if the result has many trailing 0s eg:
1.6 becomes 1.6000000000000000
I tried round(6.2,15) but it returns 6.2000000000000002 adding a rounding error
I also saw various people online who put the float into a string and then added trailing 0's manually but that seems bad...
What is the best way to do this?
For Python versions in 2.6+ and 3.x
You can use the str.format method. Examples:
>>> print('{0:.16f}'.format(1.6))
1.6000000000000001
>>> print('{0:.15f}'.format(1.6))
1.600000000000000
Note the 1 at the end of the first example is rounding error; it happens because exact representation of the decimal number 1.6 requires an infinite number binary digits. Since floating-point numbers have a finite number of bits, the number is rounded to a nearby, but not equal, value.
For Python versions prior to 2.6 (at least back to 2.0)
You can use the "modulo-formatting" syntax (this works for Python 2.6 and 2.7 too):
>>> print '%.16f' % 1.6
1.6000000000000001
>>> print '%.15f' % 1.6
1.600000000000000
The cleanest way in modern Python >=3.6, is to use an f-string with string formatting:
>>> var = 1.6
>>> f"{var:.15f}"
'1.600000000000000'
Floating point numbers lack precision to accurately represent "1.6" out to that many decimal places. The rounding errors are real. Your number is not actually 1.6.
Check out: http://docs.python.org/library/decimal.html
I guess this is essentially putting it in a string, but this avoids the rounding error:
import decimal
def display(x):
digits = 15
temp = str(decimal.Decimal(str(x) + '0' * digits))
return temp[:temp.find('.') + digits + 1]
We can use format() to print digits after the decimal places.
Taken from http://docs.python.org/tutorial/floatingpoint.html
>>> format(math.pi, '.12g') # give 12 significant digits
'3.14159265359'
>>> format(math.pi, '.2f') # give 2 digits after the point
'3.14'

Is there a more readable or Pythonic way to format a Decimal to 2 places?

What the heck is going on with the syntax to fix a Decimal to two places?
>>> from decimal import Decimal
>>> num = Decimal('1.0')
>>> num.quantize(Decimal(10) ** -2) # seriously?!
Decimal('1.00')
Is there a better way that doesn't look so esoteric at a glance? 'Quantizing a decimal' sounds like technobabble from an episode of Star Trek!
Use string formatting:
>>> from decimal import Decimal
>>> num = Decimal('1.0')
>>> format(num, '.2f')
'1.00'
The format() function applies string formatting to values. Decimal() objects can be formatted like floating point values.
You can also use this to interpolate the formatted decimal value is a larger string:
>>> 'Value of num: {:.2f}'.format(num)
'Value of num: 1.00'
See the format string syntax documentation.
Unless you know exactly what you are doing, expanding the number of significant digits through quantisation is not the way to go; quantisation is the privy of accountancy packages and normally has the aim to round results to fewer significant digits instead.
Quantize is used to set the number of places that are actually held internally within the value, before it is converted to a string. As Martijn points out this is usually done to reduce the number of digits via rounding, but it works just as well going the other way. By specifying the target as a decimal number rather than a number of places, you can make two values match without knowing specifically how many places are in them.
It looks a little less esoteric if you use a decimal value directly instead of trying to calculate it:
num.quantize(Decimal('0.01'))
You can set up some constants to hide the complexity:
places = [Decimal('0.1') ** n for n in range(16)]
num.quantize(places[2])

Simple Basic Python compare

I found this interesting question when I was doing homework
we know, 47.36/1.6**2 == 18.5
but when I try to run the following code, it gives me a False(should be true)
print 47.36/1.6**2 == 18.5
Do anyone know what's going on?
You're probably getting an answer like 18.49999999999, which is not exactly equal to 18.5.
As always, the relevant reference for this is What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Short answer: IEEE 754 floating point can't exactly represent fractions where the denominator isn't a power of two, like 1/4, 1/16, 1/256, etc. You can get awfully close, given enough digits, but never quite exactly there.
You compare floating point numbers by defining "equals" as "within a certain delta". You could write something like:
def almost_equals(a, b, delta=0.0005):
return abs(a - b) <= delta
and then test for "probably equal" with:
>>> almost_equals(47.36/1.6**2, 18.5)
True
I would avoid checking for exact equality when comparing two floats. Instead take the difference and see if it is smaller than a value you consider close to zero.
(47.36/1.6**2 - 18.5) < 0.00000000001
will be
True
>>> 47.36/1.6**2
18.499999999999996
See this page on Floating Point Arithmetic: Issues and Limitations.
Here is how you can calculate this to exactly 18.5 without using any rounding or "close enough" behavior by using the decimal module:
>>> from decimal import Decimal
>>> Decimal('47.36') / Decimal('1.6')**2 == Decimal('18.5')
True
>>> float(Decimal('47.36') / Decimal('1.6')**2) == 18.5
True
As others have said:
>>> 47.36/1.6**2
18.499999999999996
But, this is NOT due to a floating-point arithmetic problem as far as I can tell. Even if you use decimal math by wrapping the operands in Decimal() (after from decimal import Decimal) you will still get Decimal('18.49999999999999772404279952') as the answer.
It's possible I'm using Decimal() wrong here and my result also has some sort of floating point error; however, if I'm correct, that expression flat out does not equal 18.5, no matter what kind of math you use.
Edit: As Greg points out in the comments, the problem with my approach here is that Decimal(1.6) will just convert the float representation of 1.6, inaccuracies intact, into a Decimal. This gives the correct answer:
>>> Decimal('47.36') / Decimal('1.6')**2
Decimal('18.5')
Better still would be to use the fractions module as suggested by Kirk.
47.36/1.6*2 return integer. So 47.36/1.6*2 would be 18, which is not equal to 18.5.
Edit
Sorry about that, actually it is being stored as 18.499999.
You should do this
import numpy as np
print np.around((47.36/1.6**2), decimals=1) == 18.5
This would return True.

Converting a float to a string without rounding it

I'm making a program that, for reasons not needed to be explained, requires a float to be converted into a string to be counted with len(). However, str(float(x)) results in x being rounded when converted to a string, which throws the entire thing off. Does anyone know of a fix for it?
Here's the code being used if you want to know:
len(str(float(x)/3))
Some form of rounding is often unavoidable when dealing with floating point numbers. This is because numbers that you can express exactly in base 10 cannot always be expressed exactly in base 2 (which your computer uses).
For example:
>>> .1
0.10000000000000001
In this case, you're seeing .1 converted to a string using repr:
>>> repr(.1)
'0.10000000000000001'
I believe python chops off the last few digits when you use str() in order to work around this problem, but it's a partial workaround that doesn't substitute for understanding what's going on.
>>> str(.1)
'0.1'
I'm not sure exactly what problems "rounding" is causing you. Perhaps you would do better with string formatting as a way to more precisely control your output?
e.g.
>>> '%.5f' % .1
'0.10000'
>>> '%.5f' % .12345678
'0.12346'
Documentation here.
len(repr(float(x)/3))
However I must say that this isn't as reliable as you think.
Floats are entered/displayed as decimal numbers, but your computer (in fact, your standard C library) stores them as binary. You get some side effects from this transition:
>>> print len(repr(0.1))
19
>>> print repr(0.1)
0.10000000000000001
The explanation on why this happens is in this chapter of the python tutorial.
A solution would be to use a type that specifically tracks decimal numbers, like python's decimal.Decimal:
>>> print len(str(decimal.Decimal('0.1')))
3
Other answers already pointed out that the representation of floating numbers is a thorny issue, to say the least.
Since you don't give enough context in your question, I cannot know if the decimal module can be useful for your needs:
http://docs.python.org/library/decimal.html
Among other things you can explicitly specify the precision that you wish to obtain (from the docs):
>>> getcontext().prec = 6
>>> Decimal('3.0')
Decimal('3.0')
>>> Decimal('3.1415926535')
Decimal('3.1415926535')
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85987')
>>> getcontext().rounding = ROUND_UP
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85988')
A simple example from my prompt (python 2.6):
>>> import decimal
>>> a = decimal.Decimal('10.000000001')
>>> a
Decimal('10.000000001')
>>> print a
10.000000001
>>> b = decimal.Decimal('10.00000000000000000000000000900000002')
>>> print b
10.00000000000000000000000000900000002
>>> print str(b)
10.00000000000000000000000000900000002
>>> len(str(b/decimal.Decimal('3.0')))
29
Maybe this can help?
decimal is in python stdlib since 2.4, with additions in python 2.6.
Hope this helps,
Francesco
I know this is too late but for those who are coming here for the first time, I'd like to post a solution. I have a float value index and a string imgfile and I had the same problem as you. This is how I fixed the issue
index = 1.0
imgfile = 'data/2.jpg'
out = '%.1f,%s' % (index,imgfile)
print out
The output is
1.0,data/2.jpg
You may modify this formatting example as per your convenience.

Categories

Resources