Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. qRound() in Qt

qRound() in Qt

Scheduled Pinned Locked Moved Solved General and Desktop
roundqround
20 Posts 5 Posters 28.5k 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.
  • divergerD Offline
    divergerD Offline
    diverger
    wrote on last edited by diverger
    #1

    I found there is a qRound() function in Qt, the doc only says:

    int qRound(qfloat16 value)
    Rounds value to the nearest integer.
    See also qRound. 
    

    What's the difference with the std::round() function? Any reason to add qRound() function?

    1 Reply Last reply
    0
    • aha_1980A Offline
      aha_1980A Offline
      aha_1980
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi @diverger

      Most Qt functions of this kind are very old and were introduced in times there was no equivalent in the C++ STL or the STL was incomplete for at least one the supported platforms.

      For your example: std::round() was introduced for C++11: so it is quite new.

      Qt has to stay free or it will die.

      divergerD 1 Reply Last reply
      4
      • VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by VRonin
        #3

        std::round() manages floating point errors better (should also be thread safe but need to double check fenv_t being actually thread local).

        Normally the only reason to use q* functions over std::* functions is indeed thread safety.

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        JonBJ 1 Reply Last reply
        4
        • VRoninV VRonin

          std::round() manages floating point errors better (should also be thread safe but need to double check fenv_t being actually thread local).

          Normally the only reason to use q* functions over std::* functions is indeed thread safety.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @VRonin
          Just so I can check I do understand, the only issue for "thread safety" for this would be if another thread were in the process of altering fenv_t (which would be pretty unusual), right?

          VRoninV 1 Reply Last reply
          0
          • JonBJ JonB

            @VRonin
            Just so I can check I do understand, the only issue for "thread safety" for this would be if another thread were in the process of altering fenv_t (which would be pretty unusual), right?

            VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by
            #5

            @JonB some functions (the most famous being std::rand) might trigger race conditions if called at the same time from 2 different threads (in the example because the random seed is shared across multiple threads).

            I checked and the float environment is thread local so safe to use std::round over qRound

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            divergerD 1 Reply Last reply
            3
            • aha_1980A aha_1980

              Hi @diverger

              Most Qt functions of this kind are very old and were introduced in times there was no equivalent in the C++ STL or the STL was incomplete for at least one the supported platforms.

              For your example: std::round() was introduced for C++11: so it is quite new.

              divergerD Offline
              divergerD Offline
              diverger
              wrote on last edited by
              #6

              @aha_1980 I don't know if qRound() is introduced before std::round() or not. Just want to know their differences, and their use cases.

              1 Reply Last reply
              0
              • VRoninV VRonin

                @JonB some functions (the most famous being std::rand) might trigger race conditions if called at the same time from 2 different threads (in the example because the random seed is shared across multiple threads).

                I checked and the float environment is thread local so safe to use std::round over qRound

                divergerD Offline
                divergerD Offline
                diverger
                wrote on last edited by
                #7

                @VRonin It seems the qRound() and std::round() will output different values for some same arguments. Right?

                VRoninV 1 Reply Last reply
                0
                • divergerD diverger

                  @VRonin It seems the qRound() and std::round() will output different values for some same arguments. Right?

                  VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by VRonin
                  #8

                  @diverger said in qRound() in Qt:

                  Right?

                  Unless you go to border cases with stuff like 99.55555555555 they should give you the same answer

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  divergerD JonBJ 2 Replies Last reply
                  0
                  • VRoninV VRonin

                    @diverger said in qRound() in Qt:

                    Right?

                    Unless you go to border cases with stuff like 99.55555555555 they should give you the same answer

                    divergerD Offline
                    divergerD Offline
                    diverger
                    wrote on last edited by
                    #9

                    @VRonin Please try the code below:

                    double b = -0.5;
                    
                    qDebug() << std::round(b);
                    qDebug() << qRound(b);
                    
                    

                    Qt 5.10.1 + VS2015, give me:

                    -1
                    0
                    
                    JonBJ 1 Reply Last reply
                    1
                    • VRoninV Offline
                      VRoninV Offline
                      VRonin
                      wrote on last edited by VRonin
                      #10

                      Both are valid answers, it's just your question that's abiguous

                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                      ~Napoleon Bonaparte

                      On a crusade to banish setIndexWidget() from the holy land of Qt

                      1 Reply Last reply
                      3
                      • divergerD diverger

                        @VRonin Please try the code below:

                        double b = -0.5;
                        
                        qDebug() << std::round(b);
                        qDebug() << qRound(b);
                        
                        

                        Qt 5.10.1 + VS2015, give me:

                        -1
                        0
                        
                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by JonB
                        #11

                        Whoever downvoted @VRonin's answer, please don't (unless it was a mis-click!), as his answer was correct.

                        @diverger
                        Both std::round() and qRound() round to an integer. However, they may not necessarily round to the same integer in the case of X.5 because there is no "correct"/"unambiguous" answer in that case. The implementation might round either up or down, and might differ in which way they round X.5 versus -X.5.

                        So you appear to have found different behaviour, at least in the case of -0.5. Both results are "correct". If you really care in such a case, you may find you prefer the behaviour of one over the other, in which case use that one, or adjust your calling code as desired.

                        divergerD kshegunovK 2 Replies Last reply
                        2
                        • JonBJ JonB

                          Whoever downvoted @VRonin's answer, please don't (unless it was a mis-click!), as his answer was correct.

                          @diverger
                          Both std::round() and qRound() round to an integer. However, they may not necessarily round to the same integer in the case of X.5 because there is no "correct"/"unambiguous" answer in that case. The implementation might round either up or down, and might differ in which way they round X.5 versus -X.5.

                          So you appear to have found different behaviour, at least in the case of -0.5. Both results are "correct". If you really care in such a case, you may find you prefer the behaviour of one over the other, in which case use that one, or adjust your calling code as desired.

                          divergerD Offline
                          divergerD Offline
                          diverger
                          wrote on last edited by
                          #12

                          @JonB I don't mean qRound() is wrong in his behavior. And I know also there are some many rounding methods when x.5 is given to these function. I just want to know more about the function, what's is main purpose to add it to Qt. As Qt only give a simple word in it's doc. When I found the qRound() function in the doc, I think it's just as the doc say "round -to-nearest", but finally I found it will give me different result from some others. And at last, I found the function I need is actually the more recent "rint()".

                          So, I just want know more about this function.

                          1 Reply Last reply
                          1
                          • VRoninV Offline
                            VRoninV Offline
                            VRonin
                            wrote on last edited by
                            #13

                            qRound():
                            https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#_Z6qRoundd

                            So if decimalPart(abs(d)) < 0.5 rounds down otherwise round up

                            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                            ~Napoleon Bonaparte

                            On a crusade to banish setIndexWidget() from the holy land of Qt

                            1 Reply Last reply
                            4
                            • JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on last edited by
                              #14

                              See also https://stackoverflow.com/questions/47156806/stdnearbyint-vs-stdround-in-c11 for all the complexities/variants etc. of the std:: equivalents.

                              1 Reply Last reply
                              3
                              • JonBJ JonB

                                Whoever downvoted @VRonin's answer, please don't (unless it was a mis-click!), as his answer was correct.

                                @diverger
                                Both std::round() and qRound() round to an integer. However, they may not necessarily round to the same integer in the case of X.5 because there is no "correct"/"unambiguous" answer in that case. The implementation might round either up or down, and might differ in which way they round X.5 versus -X.5.

                                So you appear to have found different behaviour, at least in the case of -0.5. Both results are "correct". If you really care in such a case, you may find you prefer the behaviour of one over the other, in which case use that one, or adjust your calling code as desired.

                                kshegunovK Offline
                                kshegunovK Offline
                                kshegunov
                                Moderators
                                wrote on last edited by kshegunov
                                #15

                                @JonB said in qRound() in Qt:

                                However, they may not necessarily round to the same integer in the case of X.5 because there is no "correct"/"unambiguous" answer in that case. The implementation might round either up or down, and might differ in which way they round X.5 versus -X.5.

                                As Luca pointed out, this is "controllable" (albeit not as good as we'd like) through the floating point environment - i.e. whether rounding should be up, down or to nearest. From my experience, by default round to nearest is preferred, however this is not set in stone.

                                PS. The above is for std::round, while Qt's qRound implementation is rather suspicious. It's not aware of the floating point environment, it basically goes like this:

                                int qRound(double x)
                                {
                                    return x + 0.5; // Will round to nearest, but there's no control over the behavior and one works if you want integers, it can't be used to round fp type to some predefined precision.
                                }
                                

                                Read and abide by the Qt Code of Conduct

                                1 Reply Last reply
                                4
                                • VRoninV VRonin

                                  @diverger said in qRound() in Qt:

                                  Right?

                                  Unless you go to border cases with stuff like 99.55555555555 they should give you the same answer

                                  JonBJ Offline
                                  JonBJ Offline
                                  JonB
                                  wrote on last edited by
                                  #16

                                  @VRonin said in qRound() in Qt:

                                  Unless you go to border cases with stuff like 99.55555555555 they should give you the same answer

                                  While we're being all very precise about this rounding issue ( :) ), I meant to pick you up on this. What is "border case" about this? It's unambiguously 100! Perhaps you had mind "rounding to n - 1 decimal places" here?

                                  VRoninV 1 Reply Last reply
                                  1
                                  • JonBJ JonB

                                    @VRonin said in qRound() in Qt:

                                    Unless you go to border cases with stuff like 99.55555555555 they should give you the same answer

                                    While we're being all very precise about this rounding issue ( :) ), I meant to pick you up on this. What is "border case" about this? It's unambiguously 100! Perhaps you had mind "rounding to n - 1 decimal places" here?

                                    VRoninV Offline
                                    VRoninV Offline
                                    VRonin
                                    wrote on last edited by
                                    #17

                                    @JonB said in qRound() in Qt:

                                    It's unambiguously 100!

                                    Yep, sorry I meant 99.49999999999 but even that is unabiguous

                                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                    ~Napoleon Bonaparte

                                    On a crusade to banish setIndexWidget() from the holy land of Qt

                                    JonBJ 1 Reply Last reply
                                    0
                                    • VRoninV VRonin

                                      @JonB said in qRound() in Qt:

                                      It's unambiguously 100!

                                      Yep, sorry I meant 99.49999999999 but even that is unabiguous

                                      JonBJ Offline
                                      JonBJ Offline
                                      JonB
                                      wrote on last edited by
                                      #18

                                      @VRonin
                                      Ah, OK, just checking I wasn't aware of something.

                                      Actually your .49999999999 kind of, in principle holds, and is worthy of mention, not as "ambiguous" but as "border case", insofar as it warns of the limits of floating point precision in an fp implementation.

                                      It would probably require a few more decimal places in a double, but users should be aware that all fp values are indeed approximate, which can show up in such "edge cases". Thus it is not necessarily the case that:

                                      99.49999999999999999999999 + 0.5 == 99.99999999999999999999999
                                      

                                      In some implementations/hardware environments it might equal that, but in others it might equal, say, 100.0.

                                      And this is significant, because in what we have been discussing even with the same rounding algorithm the result of the integer round might be 99 in one implementation and 100 in another as a result of this precision issue.

                                      VRoninV 1 Reply Last reply
                                      0
                                      • JonBJ JonB

                                        @VRonin
                                        Ah, OK, just checking I wasn't aware of something.

                                        Actually your .49999999999 kind of, in principle holds, and is worthy of mention, not as "ambiguous" but as "border case", insofar as it warns of the limits of floating point precision in an fp implementation.

                                        It would probably require a few more decimal places in a double, but users should be aware that all fp values are indeed approximate, which can show up in such "edge cases". Thus it is not necessarily the case that:

                                        99.49999999999999999999999 + 0.5 == 99.99999999999999999999999
                                        

                                        In some implementations/hardware environments it might equal that, but in others it might equal, say, 100.0.

                                        And this is significant, because in what we have been discussing even with the same rounding algorithm the result of the integer round might be 99 in one implementation and 100 in another as a result of this precision issue.

                                        VRoninV Offline
                                        VRoninV Offline
                                        VRonin
                                        wrote on last edited by
                                        #19

                                        @JonB I'm not qualified to give opionons on this, I'll just ask @kshegunov's help.
                                        I thought error of double was always in defect so, since 0.5 is perfectly represented in double, the double representation of 99.49999999999999999999999 + 0.5 will always be <= 99.99999999999999999999999

                                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                        ~Napoleon Bonaparte

                                        On a crusade to banish setIndexWidget() from the holy land of Qt

                                        kshegunovK 1 Reply Last reply
                                        0
                                        • VRoninV VRonin

                                          @JonB I'm not qualified to give opionons on this, I'll just ask @kshegunov's help.
                                          I thought error of double was always in defect so, since 0.5 is perfectly represented in double, the double representation of 99.49999999999999999999999 + 0.5 will always be <= 99.99999999999999999999999

                                          kshegunovK Offline
                                          kshegunovK Offline
                                          kshegunov
                                          Moderators
                                          wrote on last edited by
                                          #20

                                          @VRonin said in qRound() in Qt:

                                          I thought error of double was always in defect

                                          No not necessarily. Depends on the number you are trying to represent. Consider 2/3 in decimal floating point (opposed to the binary used in computers, just for simplicity) as an example, that'd give you 0.6(6..)7 as the last digit would be rounded up if you use round-to-nearest. Same consideration applies for binary digits. The usual floating point's fraction is represented, as is known (ignoring all the normalizations and such), as the sum:

                                          Number = Sum(i_k / 2^k)
                                          

                                          Where i_k is the k-th binary digit (either 0 or 1) and 2^k is the k-th power of 2. Same as with the decimal case, except the base is 2. Then the question becomes whether the after-the-last representable digit is rounded up or down. That's why one says that sqrt is accurate to 0.5 epsilons, as the actual calculation is performed in extended precision and then the result is rounded to the representable double type. This means the error from rounding is bound by half an epsilon - i.e. whether it was rounded up or down.

                                          Read and abide by the Qt Code of Conduct

                                          1 Reply Last reply
                                          2

                                          • Login

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