From: <bc...@wo...> - 2001-01-03 10:54:47
|
[Scott Knight] >Hello, my name is Scott and I am a Python newbie (2 months). >"hello Scott, what brought you here?" >;^) > >Anyway, I am having the time of my programming life learning Python and >building a serious configuration program in Java/Jython. What I have >noticed when I am doing some loops is an annoying precision error that I >need to work around. The simple code: > >#! /usr/bin/python > >test_var = 0.0 >limit = 0.1 >inc = 0.01 > >while test_var <= limit: > print test_var > test_var = test_var + inc > >always runs to 1 less loop than I need because of this output: > >D:\dev\python\test>jython test_loop.py >0.0 >0.01 >0.02 >0.03 >0.04 >0.05 >0.060000000000000005 >0.07 >0.08 >0.09 >0.09999999999999999 > >With native Python 2.0 in the same platform and 1.52 on Linux, the >output is a little different: > >D:\dev\python\test>test_loop.py >0.0 >0.01 >0.02 >0.03 >0.04 >0.05 >0.06 >0.07 >0.08 >0.09 >0.1 First a huge disclaimer: I know nothing about float point numbers or the strangeness of their implementation. I think CPython-2.0 is faking the output above. If you add a repr(test_var) on the print statement, you get (with CPython-2.0 & win2k): 0.0 0.0 0.01 0.01 0.02 0.02 0.03 0.029999999999999999 0.04 0.040000000000000001 0.05 0.050000000000000003 0.06 0.060000000000000005 0.07 0.070000000000000007 0.08 0.080000000000000002 0.09 0.089999999999999997 0.1 0.099999999999999992 >This is a little more of what I expected. This trivial example looks >harmless enough, but it gets out of hand when the loops are in the 100+ >range. What happens is even the Python only runs to 0.99 instead of 1.0 >like it should. Because the actual value of the float is about as imprecise in CPython as it is in Jython and in java. >The only solution I have come up with is to slightly modify the >increment like: > > test_var = round((test_var + inc), 2) > >so that it cuts off the value every time through. This seems to work >well enough, but I am wondering if there is a better way. > >I also wonder why Jython puts so many decimal places out when Python >keeps the original max of 2. This seems like it could be a Java thing >to me since I have seen similar behavior in Java programs. Jython is getting all its float behavior from java, including the string representation. This cause some difference between CPython, in particular with CPython-2.0 where the str(0.1) and repr(0.1) return different string values (at least is does in my w2k). I don't think the jython implementation of floats and float -> string conversion will be changed much. It has its flaws, but it is consistent with java, and java floats are consistent across platforms. That alone is a valuable improvement compared to CPython (this conclusion is reached based on reading python-dev, not on any actual knowledge of CPython). If jython will be changed to closer compliance with CPython, it will not be done by me. I'll leave that for experts on floating point implementations. regards, finn |