Number changing when inserted into list [duplicate] - python

This question already has answers here:
python floating number [duplicate]
(4 answers)
Closed 8 years ago.
I'm only going to paste part of my code since it's very long, but I was wondering if any one might know potential causes of this problem. So I have this code here:
print "part a", working_weight
cells[working_cell_position][4] = working_weight
print "part b", working_weight, cells[working_cell_position][4], cells[working_cell_position]
and what it prints is this:
part a 62.4
part b 62.4 62.4 [6, 6, '', '', 62.400000000000006]
So if you didn't quite get it, basically I have the variable working_weight which is 62.4, but when I insert it into a list, it changes it to 62.400000000000006, yet if I only print that number from the list it prints as 62.4 still. If anyone could help, or suggest a solution to fix this it would be greatly appreciated.

This is because floats are inherently imprecise in pretty much every language, as they cannot be represented easily in 64-bit binary at the lowest level. What is happening to your code has nothing to do with how it is put into the list or anything like that.
If you want to keep a precise decimal you should use decimal.Decimal.
>>> from decimal import Decimal
>>> working_weight = Decimal(str(working_weight))
>>> working_weight
Decimal('62.4')
This Decimal can then have operations performed on it like any float.

Floating point math is tough, that's the problem. If you have decimals, use decimal.Decimal.
from decimal import Decimal
a = Decimal("30")
b = Decimal("32.4")
print(a+b)
# Decimal ('62.4')

It's hard to say for sure without having a reproducible problem, but one way to get something similar is for example
import numpy
a = numpy.array([62.4], numpy.float)
print a[0] # outputs 62.4
print [a[0]] # outputs [62.399999999999999]
where is working_height coming from? What is working_height.__class__?

Related

Concatenate numbers in binary [duplicate]

This question already has answers here:
Python int to binary string?
(36 answers)
Closed 6 years ago.
When converting a number in binary in Python what you get is the following:
b = bin(77)
print(b) # 0b1001101
When I was expecting 01001101. I am guessing that the b is there to let Python know that this is a binary number and not some integer. And that is ok within Python but what is considered safe practise here if you want to communicate with the outside world? This might be a silly example but online converters for instance do not recognise the above binary.
Would simply removing b always do the trick? Because I seem to be running into problems trying to code the Ascii85 encoder/decoder where concatenations of binary numbers take place. You can take a look at this example here.
My code is this case produces the following:
ch = 'Man '
list_ = [ord(x) for x in ch] # [77, 97, 110, 32]
binary_repr = ''.join(bin(x) for x in list_) # 0b10011010b11000010b11011100b100000
# When it should be 01001101011000010110111000100000
Notice that simply replacing the b with nothing doesn't quite cut it here. This is probably some dumm mistake but can someone clear things up for me?
>>> format(b, '08b')
Where b is your number and '08b' is the number of bit you want to use representing your number, if the parameter is #08b instead of 08b, you get the 0b in front of the number.
use format in every further operation and you should be good!
Doesn't
str(b)[2:]
do the job?
But you'll maybe better do:
"{0:b}".format(77)

numpy float32 truncating decimal [duplicate]

This question already has answers here:
How to set the precision on str(numpy.float64)?
(5 answers)
Closed 7 years ago.
I'm working on a school project that requires me to do some math on single-precision floating point numbers. I thought I would use the float32 format in numpy as python is really the only general purpose language I know. IMO this number format should be able to handle the number 1.0000001, but it keeps truncating my answer to 1.0. The closest I can get it to handle is 1.00001. Can anyone shed any light on this? I'm new to this floating point format and Python.
import numpy as np
keyInput=np.float32(input("Enter a number and i'll float 32 it: "))
print(keyInput)
print(np.float32(keyInput))
print("This is of type: ",type(keyInput))
input('Press ENTER to exit')
First of all, print without explicit formatting or conversion is not reliable. You should try something like print "%.10f" % number instead of print number.
Second, as commentators have pointed out, you can't expect all decimal numbers gets represented precisely as floating point number. Read the Goldberg paper. It's a must read.
An example ipython session for you (I'm using Python 2.7, if you use Python 3, print is a function):
In [1]: import numpy
In [2]: print numpy.float32(1.0 + 1e-7)
1.0
In [3]: print "%.10f" % numpy.float32(1.0 + 1e-7)
1.0000001192
In [4]: print "%.10f" % numpy.float32(1.0 + 1e-8)
1.0000000000
Edit: you can use numpy to inspect type precision limits. Consult the doc of numpy.MachAr for more.
Example:
In [1]: import numpy
In [2]: machar = numpy.MachAr(float_conv=numpy.float32)
In [3]: machar.eps
Out[3]: 1.1920928955078125e-07

Rounding logic in Python? [duplicate]

This question already has answers here:
Python float to int conversion
(6 answers)
Closed 8 years ago.
In my original code I was trying to compute some indices out of some float values and I faced the following problem:
>>> print int((1.40-.3)/.05)
21
But:
>>> print ((1.40-.3)/.05)
22.0
I am speechless about what is going on. Can somebody please explain?
This is caused by floating point inaccuracy:
>>> print repr((1.40-.3)/.05)
21.999999999999996
You could try using the Decimal type instead:
>>> from decimal import Decimal
>>> Decimal
<class 'decimal.Decimal'>
and then
>>> (Decimal('1.40') - Decimal('.3')) / Decimal('.05')
Decimal('22')
The fractions.Fraction class would work too. Or, you could just round:
>>> round((1.40-.3)/.05, 10) # round to 10 decimal places
22.0
Drop the print and you'll see that the actual value is:
>>> (1.40-.3)/.05
21.999999999999996
Python 2 print() (more accurately, float.__str__) lies to you by rounding to a couple of decimal digits. Python 3 print() (again, actually float.__str__) doesn't do that, it always gives a faithful representation of the actual value (it abbreviates, but only when it doesn't change the value).
This inaccuracy is inherent to floating point numbers (including Decimal, though its inaccuracies occur different cases). This is a fundamental problem, representing arbitrary real numbers is not possible. See Is floating point math broken? for explanations.
I think this explains it straightforwardly:
import decimal
>>> (decimal.Decimal(1.40) -decimal.Decimal(.3))/decimal.Decimal(.05)
Decimal('21.99999999999999722444243843')
>>> (decimal.Decimal('1.40') -decimal.Decimal('.3'))/decimal.Decimal('.05')
Decimal('22')

Python 3.0+ setting to max 4 decimal and rounding

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

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