[PySide] Strange behaviour of QLocale.toString()

Algis Kabaila akabaila at pcug.org.au
Mon Apr 15 01:30:39 CEST 2013


Just to add a little fuel to this fire:

First, by hand try to convert the "exact" 0.1 then 0.01 decimal to their 
binary equivalent. Send to this list the binary value.  Is it exact?

Second, who would care about 1 cent in $10 000 ?

Al.

On Sunday 14 April 2013 16:04:15 Tim Doty wrote:
> On Apr 14, 2013, at 3:35 PM, Zak <pyside at m.allo.ws> wrote:
> > My original email was correct, let me provide proof and explain
> > further.
> > 
> > Let me address a few specific points:
> > 
> > Tim Doty wrote:
> > > For the PySide what is really happening is not a rounding
> > > error/precision as suggested, but printing an integer with floating
> > > point notation. When the floating point is converted to an integer
> > > it is rounded. To satisfy yourself that this is in fact happening
> > > change the number to be printed (e.g., 9999999.5 vs 9999999.4).
> > 
> > This is incorrect, what is happening is a rounding error. The number
> > is being rounded to fit in a 32 bit piece of memory. The
> > counter-example above is misleading because it uses bad values. Try
> > the values 1.4 and 1.6 instead. These values are used in the attached
> > Python script.
> As I said, I don't know the PySide internals. I referred to the
> published documentation which implies that floats are being coerced
> into integers due to lack of a float overload. Apparently the docs are
> wrong… go figure.
> 
> Interestingly, if you drop the millions (e.g., 999999.62) you can see
> the rounding in action. I'm not going to dredge through a wall of text
> looking for a point in the preceding post, but -- as it so happens --
> the example I give above outputs correctly making it seem as if there
> is inconsistent precision. But it is an accident. 999999.65 also prints
> as 999999.62 while 999999.66 prints as 999999.69
> 
> So it is just an artifact of 32-bit precision float representations.
> Now, why it is being constrained to a 32-bit float on a 64-bit
> architecture is a different conversation and, while I recognize there
> would be disagreement, I call that a bug on its face and the fact that
> the sibling implementation uses 64-bit precision underscores the point.
> 
> Tim Doty
> 
> > The number is not at any point represented as an integer (data
> > structure), it is always a floating point. Even if the number's value
> > is a whole number, it is represented as a floating point. For
> > instance, Python interprets '1.0' as a floating point literal. A
> > mathematician would say 1.0 is an integer, but computer science uses
> > different terminology. In computer science, in the language Python,
> > '1' is an integer and '1.0' is a floating point, and they are equal
> > in numerical value. They are represented differently in memory.> 
> > Alexey Vihorev wrote:
> > > Two considerations:
> > > 1. No rounding should take place in this case - the decimal
> > > precision of the input and output is exactly the same.
> > > 2. In PyQt it *does* work correctly, so fundamental lows of computer
> > > science are certainly not the reason.
> > 
> > In response to 1: That is just your opinion. You do not want rounding
> > to take place. The designers of Python and Qt had a different
> > opinion. To make things faster, they decided to round numbers so that
> > they can fit in either 32 or 64 bits of memory. If you want to use
> > larger chunks of memory and keep higher precision, then you should
> > use the Python standard library 'decimal', as I said before. Using
> > decimal.Decimal objects, you can set the precision yourself. Because
> > you are not using this library, Python, PySide, and PyQt are making a
> > decision about how to round the number. PySide chose 32 bits, PyQt
> > chose 64 bits. The Python language itself chose 64 bits, so PySide
> > and PyQt cannot possibly choose higher precision, the extra bits have
> > already been thrown away.
> > 
> > In response to 2: You are using incorrect logic. As you can see from
> > my example, PyQt also suffers rounding errors, they just occur around
> > 15 to 17 digits. You didn't use that many digits so you didn't see
> > the rounding error.
> > 
> > Zak Fallows
> > 
> > # File: num_print.py
> > 
> > from PyQt4.QtCore import QLocale as PyQtLocale
> > from PySide.QtCore import QLocale as PySideLocale
> > 
> > def pb(num):
> >     """pb stands for Print Both"""
> >     
> >     print "Original: " + num
> >     flt = eval(num)
> >     print "    PyQt: ",
> >     print PyQtLocale().toString(flt, 'f', 6)
> >     print "    PySide: ",
> >     print PySideLocale().toString(flt, 'f', 6)
> >     print ''
> > 
> > test_list = [
> > 
> >     '1.4',
> >     '1.6',
> >     '1000.4',
> >     '1000.6',
> >     '10**6 + .4',
> >     '10**6 + .6',
> >     '10**7 + .4',
> >     '10**7 + .6',
> >     '10**8 + .4',
> >     '10**8 + .6',
> >     '10**9 + .4',
> >     '10**9 + .6',
> >     '10**14 + .4',
> >     '10**14 + .6',
> >     '10**15 + .4',
> >     '10**15 + .6',
> >     '10**16 + .4',
> >     '10**16 + .6',
> >     '10**17 + .4',
> >     '10**17 + .6',
> > 
> > ]
> > 
> > for num in test_list:
> >     pb(num)
> > 
> > """
> > 
> > #======================== How to Check Version Numbers
> > ========================#> 
> > PyQt:
> >     PyQt4.QtCore.PYQT_VERSION_STR
> > 
> > PySide:
> >     PySide.__version__
> > 
> > #=============================== Sample Output
> > ================================#
> > 
> > Here is some sample output from running the program:
> > 
> > #---------------------------------- Mac OS X
> > ----------------------------------#
> > 
> > Mac OS X 10.8.3
> > Python 2.7.3, 64-bit, from Python.org
> > PySide 1.1.1, 64-bit
> > PyQt 4.9.4, 64-bit
> > 
> > >>> import num_print
> > 
> > Original: 1.4
> > 
> >     PyQt:  1.400000
> >     PySide:  1.400000
> > 
> > Original: 1.6
> > 
> >     PyQt:  1.600000
> >     PySide:  1.600000
> > 
> > Original: 1000.4
> > 
> >     PyQt:  1,000.400000
> >     PySide:  1,000.400024
> > 
> > Original: 1000.6
> > 
> >     PyQt:  1,000.600000
> >     PySide:  1,000.599976
> > 
> > Original: 10**6 + .4
> > 
> >     PyQt:  1,000,000.400000
> >     PySide:  1,000,000.375000
> > 
> > Original: 10**6 + .6
> > 
> >     PyQt:  1,000,000.600000
> >     PySide:  1,000,000.625000
> > 
> > Original: 10**7 + .4
> > 
> >     PyQt:  10,000,000.400000
> >     PySide:  10,000,000.000000
> > 
> > Original: 10**7 + .6
> > 
> >     PyQt:  10,000,000.600000
> >     PySide:  10,000,001.000000
> > 
> > Original: 10**8 + .4
> > 
> >     PyQt:  100,000,000.400000
> >     PySide:  100,000,000.000000
> > 
> > Original: 10**8 + .6
> > 
> >     PyQt:  100,000,000.600000
> >     PySide:  100,000,000.000000
> > 
> > Original: 10**9 + .4
> > 
> >     PyQt:  1,000,000,000.400000
> >     PySide:  1,000,000,000.000000
> > 
> > Original: 10**9 + .6
> > 
> >     PyQt:  1,000,000,000.600000
> >     PySide:  1,000,000,000.000000
> > 
> > Original: 10**14 + .4
> > 
> >     PyQt:  100,000,000,000,000.406250
> >     PySide:  100,000,000,376,832.000000
> > 
> > Original: 10**14 + .6
> > 
> >     PyQt:  100,000,000,000,000.593750
> >     PySide:  100,000,000,376,832.000000
> > 
> > Original: 10**15 + .4
> > 
> >     PyQt:  1,000,000,000,000,000.375000
> >     PySide:  999,999,986,991,104.000000
> > 
> > Original: 10**15 + .6
> > 
> >     PyQt:  1,000,000,000,000,000.625000
> >     PySide:  999,999,986,991,104.000000
> > 
> > Original: 10**16 + .4
> > 
> >     PyQt:  10,000,000,000,000,000.000000
> >     PySide:  10,000,000,272,564,224.000000
> > 
> > Original: 10**16 + .6
> > 
> >     PyQt:  10,000,000,000,000,000.000000
> >     PySide:  10,000,000,272,564,224.000000
> > 
> > Original: 10**17 + .4
> > 
> >     PyQt:  100,000,000,000,000,000.000000
> >     PySide:  99,999,998,430,674,944.000000
> > 
> > Original: 10**17 + .6
> > 
> >     PyQt:  100,000,000,000,000,000.000000
> >     PySide:  99,999,998,430,674,944.000000
> > 
> > #--------------------------------- Windows 7
> > ----------------------------------#
> > 
> > Windows 7, 64-bit
> > Python 2.7.3, 32-bit, from Python.org
> > PySide 1.1.1, 32-bit
> > PyQt 4.10, 32-bit
> > 
> > >>> import num_print
> > 
> > Original: 1.4
> > 
> >     PyQt:  1.400000
> >     PySide:  1.400000
> > 
> > Original: 1.6
> > 
> >     PyQt:  1.600000
> >     PySide:  1.600000
> > 
> > Original: 1000.4
> > 
> >     PyQt:  1,000.400000
> >     PySide:  1,000.400024
> > 
> > Original: 1000.6
> > 
> >     PyQt:  1,000.600000
> >     PySide:  1,000.599976
> > 
> > Original: 10**6 + .4
> > 
> >     PyQt:  1,000,000.400000
> >     PySide:  1,000,000.375000
> > 
> > Original: 10**6 + .6
> > 
> >     PyQt:  1,000,000.600000
> >     PySide:  1,000,000.625000
> > 
> > Original: 10**7 + .4
> > 
> >     PyQt:  10,000,000.400000
> >     PySide:  10,000,000.000000
> > 
> > Original: 10**7 + .6
> > 
> >     PyQt:  10,000,000.600000
> >     PySide:  10,000,001.000000
> > 
> > Original: 10**8 + .4
> > 
> >     PyQt:  100,000,000.400000
> >     PySide:  100,000,000.000000
> > 
> > Original: 10**8 + .6
> > 
> >     PyQt:  100,000,000.600000
> >     PySide:  100,000,000.000000
> > 
> > Original: 10**9 + .4
> > 
> >     PyQt:  1,000,000,000.400000
> >     PySide:  1,000,000,000.000000
> > 
> > Original: 10**9 + .6
> > 
> >     PyQt:  1,000,000,000.600000
> >     PySide:  1,000,000,000.000000
> > 
> > Original: 10**14 + .4
> > 
> >     PyQt:  100,000,000,000,000.406250
> >     PySide:  100,000,000,376,832.000000
> > 
> > Original: 10**14 + .6
> > 
> >     PyQt:  100,000,000,000,000.593750
> >     PySide:  100,000,000,376,832.000000
> > 
> > Original: 10**15 + .4
> > 
> >     PyQt:  1,000,000,000,000,000.375000
> >     PySide:  999,999,986,991,104.000000
> > 
> > Original: 10**15 + .6
> > 
> >     PyQt:  1,000,000,000,000,000.625000
> >     PySide:  999,999,986,991,104.000000
> > 
> > Original: 10**16 + .4
> > 
> >     PyQt:  10,000,000,000,000,000.000000
> >     PySide:  10,000,000,272,564,224.000000
> > 
> > Original: 10**16 + .6
> > 
> >     PyQt:  10,000,000,000,000,000.000000
> >     PySide:  10,000,000,272,564,224.000000
> > 
> > Original: 10**17 + .4
> > 
> >     PyQt:  100,000,000,000,000,000.000000
> >     PySide:  99,999,998,430,674,944.000000
> > 
> > Original: 10**17 + .6
> > 
> >     PyQt:  100,000,000,000,000,000.000000
> >     PySide:  99,999,998,430,674,944.000000
> > 
> > """
> > 
> > <num_print.py>
> 
> _______________________________________________
> PySide mailing list
> PySide at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/pysidea
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/pyside/attachments/20130415/d06ddb85/attachment.html>


More information about the PySide mailing list