I wouldn't call it a bug. Floating point values get rounded, that is an unavoidable part of computer science. There are two sources of rounding:
First, only a limited amount of memory is allocated for each floating point value, usually 32 or 64 bits. 32 bits can hold about 6 or 7 decimal digits of information. Your example number is 9 digits (9 significant figures), and that is more information than you can store in just 32 bits. 64 bits can hold about 15 to 17 decimal digits of information. For reference, Python floats use 64 bits (it doesn't matter whether it is a 64-bit or 32-bit version of the Python interpreter). Second, floating point values are stored in binary (base 2) format, not in decimal (base 10) format. This can cause strange imprecision. (Of note, it is possible to store floating point numbers in base 10, see the formats decimal32 and decimal64 on Wikipedia. These formats are not used by Python, C, or C++, so this is not relevant to the present discussion.) To see the problems inherent in converting between base 2 and base 10, look at the following pure Python example: >>> 0.1 * 0.1 0.010000000000000002 Why did Python return 0.010000000000000002 and not the correct answer, which is 0.01 exactly? The answer is that 0.01 (base 10) is only one significant figure in base 10, but it is non-terminating in base 2. In base 2, it is 0b0.00000010100011110101110000101... and it goes on forever, although the digits do repeat. This is similar to the base 10 number 1 / 3 = 0.3333... . Rational numbers that terminate in base 10 may be non-terminating in base 2. Because 0.01 is non-terminating in base 2, Python was forced to round the number so that it will fit in a 64 bit bucket. When converted back to base 10, the rounded result is 0.010000000000000002. Notice that this is 17 significant figures, and remember that 64 bits can hold 15 to 17 decimal digits. It has come full-circle. The matter is even more complicated in your example, because you are using PySide and PyQt, which use C++ internally. The number must first be converted from base 10 to base 2, then it must be rounded to fit in 64 bits for Python, then it must be converted from Python into C++. C++ has several different floating point types, one allocates 32 bits, one allocates 64 bits. I don't know which type PySide and PyQt use, perhaps they only allocate 32 bits. In that case, it is necessary to round down from the 64 bits in Python to 32 bits for C++. After passing through so many non-exact steps, it is no wonder the value is fudged slightly. Remember that in terms of percent, the change is very small. If even small rounding is not acceptable, I would recommend the Python standard library decimal. decimal.Decimal objects store numbers in base 10, not base 2, and you can choose the precision. It is pretty great. Good luck, Zak Fallows _______________________________________________ PySide mailing list [email protected] http://lists.qt-project.org/mailman/listinfo/pyside
