Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. How to get locale-specific number string with high precision?

How to get locale-specific number string with high precision?

Scheduled Pinned Locked Moved Unsolved Qt for Python
8 Posts 2 Posters 1.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    StarterKit
    wrote on 8 Oct 2022, 21:15 last edited by
    #1

    Hi,
    I would like to represent numbers in locale-specific format and I use QLocale for this task. But I see it has low precision (I assume becuase of 32-bit float usage under the hood). Here is an example:

    from PySide6.QtCore import QLocale
    a = 196015.260
    b = 1234567890.123456789
    print(f"Value 1: {a:.2f}")
    print(f"Value 2: {QLocale().toString(a, 'f', 2)}")
    print(f"Value 3: {b:.6f}")
    print(f"Value 4: {QLocale().toString(b, 'f', 6)}")
    

    that provides this output:

    Value 1: 196015.26
    Value 2: 196 015,27
    Value 3: 1234567890.123457
    Value 4: 1 234 567 936,000000
    

    As you may see QLocale.toString() method handles only about 7 digits correctly (that is expected precision for float32).

    Is there a way to make toString() more precise? Or is there an alternative way to convert a number string '1234567890.123456789' into locale-specific representation without losing precision?

    J 1 Reply Last reply 8 Oct 2022, 21:43
    0
    • S StarterKit
      8 Oct 2022, 21:15

      Hi,
      I would like to represent numbers in locale-specific format and I use QLocale for this task. But I see it has low precision (I assume becuase of 32-bit float usage under the hood). Here is an example:

      from PySide6.QtCore import QLocale
      a = 196015.260
      b = 1234567890.123456789
      print(f"Value 1: {a:.2f}")
      print(f"Value 2: {QLocale().toString(a, 'f', 2)}")
      print(f"Value 3: {b:.6f}")
      print(f"Value 4: {QLocale().toString(b, 'f', 6)}")
      

      that provides this output:

      Value 1: 196015.26
      Value 2: 196 015,27
      Value 3: 1234567890.123457
      Value 4: 1 234 567 936,000000
      

      As you may see QLocale.toString() method handles only about 7 digits correctly (that is expected precision for float32).

      Is there a way to make toString() more precise? Or is there an alternative way to convert a number string '1234567890.123456789' into locale-specific representation without losing precision?

      J Online
      J Online
      JonB
      wrote on 8 Oct 2022, 21:43 last edited by
      #2

      @StarterKit
      What does

      print(f"Value 4: {QString.number(b, 'f', 6)}")
      

      produce?

      S 1 Reply Last reply 8 Oct 2022, 21:52
      0
      • J JonB
        8 Oct 2022, 21:43

        @StarterKit
        What does

        print(f"Value 4: {QString.number(b, 'f', 6)}")
        

        produce?

        S Offline
        S Offline
        StarterKit
        wrote on 8 Oct 2022, 21:52 last edited by
        #3

        @JonB, I probably missed something... but I thought that Qt uses native str in Python instead of QString. May you advise me how to import QString properly if I'm wrong?

        J 1 Reply Last reply 8 Oct 2022, 22:02
        0
        • S StarterKit
          8 Oct 2022, 21:52

          @JonB, I probably missed something... but I thought that Qt uses native str in Python instead of QString. May you advise me how to import QString properly if I'm wrong?

          J Online
          J Online
          JonB
          wrote on 8 Oct 2022, 22:02 last edited by JonB 10 Aug 2022, 22:05
          #4

          @StarterKit
          Would depend on PySide/PyQt, and I don't know. I'm trying to find an alternative to QLocale().toString(). It is not clear whether this is a QLocale() issue or a floating point perhaps float/double issue between Python and Qt/C++. I am guessing/presuming b = 1234567890.123456789 fits into a double and that is what Python uses? I wouldn't know if Python uses more precision than that.

          S 1 Reply Last reply 9 Oct 2022, 12:02
          0
          • J JonB
            8 Oct 2022, 22:02

            @StarterKit
            Would depend on PySide/PyQt, and I don't know. I'm trying to find an alternative to QLocale().toString(). It is not clear whether this is a QLocale() issue or a floating point perhaps float/double issue between Python and Qt/C++. I am guessing/presuming b = 1234567890.123456789 fits into a double and that is what Python uses? I wouldn't know if Python uses more precision than that.

            S Offline
            S Offline
            StarterKit
            wrote on 9 Oct 2022, 12:02 last edited by
            #5

            @JonB, I use PySide, but either not sure is there any difference with PyQt or not.
            I would suspect some float/double issue between Python and Qt/C++ becase if we look at QLocale Class description we see 2 different methods:

            QString 	toString(double f, char format = 'g', int precision = 6) const
            QString 	toString(float f, char format = 'g', int precision = 6) const
            

            But instead of float/double Python has only one float type that is effectively double in C++. So I may suspect that a call of toString() method from Python is mapped to
            QString toString(float f, char format = 'g', int precision = 6) const
            instead of
            QString toString(float f, char format = 'g', int precision = 6) const

            J 2 Replies Last reply 9 Oct 2022, 12:11
            0
            • S StarterKit
              9 Oct 2022, 12:02

              @JonB, I use PySide, but either not sure is there any difference with PyQt or not.
              I would suspect some float/double issue between Python and Qt/C++ becase if we look at QLocale Class description we see 2 different methods:

              QString 	toString(double f, char format = 'g', int precision = 6) const
              QString 	toString(float f, char format = 'g', int precision = 6) const
              

              But instead of float/double Python has only one float type that is effectively double in C++. So I may suspect that a call of toString() method from Python is mapped to
              QString toString(float f, char format = 'g', int precision = 6) const
              instead of
              QString toString(float f, char format = 'g', int precision = 6) const

              J Online
              J Online
              JonB
              wrote on 9 Oct 2022, 12:11 last edited by JonB 10 Sept 2022, 12:12
              #6

              @StarterKit
              I am aware of this. [Your "instead of" example should be using the double overload rather than the same float one.] That is why I was asking you to find some Qt call other than QLocale().toString(), which is acceptable to PySide so not QString, where we can (try to) test whether it behaves the same or differently wrt the precision and the possible float/double issue.

              1 Reply Last reply
              0
              • S StarterKit
                9 Oct 2022, 12:02

                @JonB, I use PySide, but either not sure is there any difference with PyQt or not.
                I would suspect some float/double issue between Python and Qt/C++ becase if we look at QLocale Class description we see 2 different methods:

                QString 	toString(double f, char format = 'g', int precision = 6) const
                QString 	toString(float f, char format = 'g', int precision = 6) const
                

                But instead of float/double Python has only one float type that is effectively double in C++. So I may suspect that a call of toString() method from Python is mapped to
                QString toString(float f, char format = 'g', int precision = 6) const
                instead of
                QString toString(float f, char format = 'g', int precision = 6) const

                J Online
                J Online
                JonB
                wrote on 9 Oct 2022, 12:34 last edited by JonB 10 Sept 2022, 13:30
                #7

                @StarterKit
                I can only test with the following: Linux, Qt 5.12, PySide2-5.13, PyQt 5.14, Python 3.8.10.

                With PySide2 I get the same as you (PySide6):

                Value 1: 196015.26
                Value 2: 196,015.27
                Value 3: 1234567890.123457
                Value 4: 1,234,567,936.000000
                

                However, same code, with PyQt5 I get:

                Value 1: 196015.26
                Value 2: 196,015.26
                Value 3: 1234567890.123457
                Value 4: 1,234,567,890.123457
                

                That tells you that Qt's (C++) QLocale() is looking good. (I didn't test it in C++, but I think we can assume it works fine.) PyQt5 gets the right values too no problem. So the Python version is not an issue an either.

                Which leaves us specifically with PySide, 2 or 6, and however it binds to the Qt call. Which does a bit float-y rather than double-y. Which, if I may say so, is familiarly depressing. After a long time of being out, PySide is still full of holes and not as robust as PyQt. TQtC have had a lot of time to make it as good, and claim to support Python alongside C++, but in practice I have only ever seen Python/PySide as a second-class citizen.

                Now, here is an interesting addition to your test code with PySide:

                    print(f"toDouble(): {QLocale().toDouble(str(b))}")
                    # Output: toDouble(): (1234567890.1234567, True)
                

                This shows (a) QLocale is handling doubles again correctly and (b) PySide2 seems here to correctly pass back a double, e.g. it does not automatically convert doubles to floats or similar.

                I am unable to spot a different function which might take a double and produce a locale-string from it. So unless someone else can, that leaves you with possibly reporting it as a PySide6 bug and see what happens when?

                Maybe as a workaround you do not need to use Qt's QLocale for this? The rest of your code is Python-only, not Qt. Python has its own locale-strings handling, perhaps you could use that instead of the broken QLocale one?

                S 1 Reply Last reply 9 Oct 2022, 21:18
                1
                • J JonB
                  9 Oct 2022, 12:34

                  @StarterKit
                  I can only test with the following: Linux, Qt 5.12, PySide2-5.13, PyQt 5.14, Python 3.8.10.

                  With PySide2 I get the same as you (PySide6):

                  Value 1: 196015.26
                  Value 2: 196,015.27
                  Value 3: 1234567890.123457
                  Value 4: 1,234,567,936.000000
                  

                  However, same code, with PyQt5 I get:

                  Value 1: 196015.26
                  Value 2: 196,015.26
                  Value 3: 1234567890.123457
                  Value 4: 1,234,567,890.123457
                  

                  That tells you that Qt's (C++) QLocale() is looking good. (I didn't test it in C++, but I think we can assume it works fine.) PyQt5 gets the right values too no problem. So the Python version is not an issue an either.

                  Which leaves us specifically with PySide, 2 or 6, and however it binds to the Qt call. Which does a bit float-y rather than double-y. Which, if I may say so, is familiarly depressing. After a long time of being out, PySide is still full of holes and not as robust as PyQt. TQtC have had a lot of time to make it as good, and claim to support Python alongside C++, but in practice I have only ever seen Python/PySide as a second-class citizen.

                  Now, here is an interesting addition to your test code with PySide:

                      print(f"toDouble(): {QLocale().toDouble(str(b))}")
                      # Output: toDouble(): (1234567890.1234567, True)
                  

                  This shows (a) QLocale is handling doubles again correctly and (b) PySide2 seems here to correctly pass back a double, e.g. it does not automatically convert doubles to floats or similar.

                  I am unable to spot a different function which might take a double and produce a locale-string from it. So unless someone else can, that leaves you with possibly reporting it as a PySide6 bug and see what happens when?

                  Maybe as a workaround you do not need to use Qt's QLocale for this? The rest of your code is Python-only, not Qt. Python has its own locale-strings handling, perhaps you could use that instead of the broken QLocale one?

                  S Offline
                  S Offline
                  StarterKit
                  wrote on 9 Oct 2022, 21:18 last edited by StarterKit 10 Sept 2022, 21:19
                  #8

                  Hi @JonB, thank your very much for your tests and inputs!
                  I mostly agree with everything you wrote. A couple more commens:

                  1. about this part

                  Maybe as a workaround you do not need to use Qt's QLocale for this? The rest of your code is Python-only, not Qt. Python has its own locale-strings handling, perhaps you could use that instead of the broken QLocale one?

                  Yes, I thought about it and indeed Python is able to do the job. Maybe I didn't dig deep enough but I found a way how to do it only via switching of locale back and forth. And Python manuals are strongly against it - they warn of various side effects that happens with locale switching and advise not to do it this way.

                  1. About workaround itself - it appears that for my needs everything is related with QLocale().decimalPoint() and QLocale().groupSeparator() so I think I'll be able to make proper replacements with my own Python code.
                  2. I'll try to report this as a bug, but a bit later, when I'll have some spare time for it.
                  1 Reply Last reply
                  0

                  4/8

                  8 Oct 2022, 22:02

                  • Login

                  • Login or register to search.
                  4 out of 8
                  • First post
                    4/8
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved