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. Bug on adding? [SOLVED]
QtWS25 Last Chance

Bug on adding? [SOLVED]

Scheduled Pinned Locked Moved General and Desktop
11 Posts 4 Posters 3.6k 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.
  • T Offline
    T Offline
    taeke
    wrote on last edited by
    #1

    Hi

    I am learning QT and have the well known assigment to "calculate the amount of change out of $xx".

    For some reason when running the program, if always changes $0.18 to $0.17. When I use different numbers, the calculation is correct, but anything with $xx.18 is wrong. Here is part of my code:

    @
    double amnt, paid;
    int change, tmp;
    QString chg="";

    amnt = QInputDialog::getDouble(0, "Register", "Enter amount to pay", 0, 0, DBL_MAX, 2);
    paid = QInputDialog::getDouble(0, "Register", "Enter amount paid", 0, 0, DBL_MAX, 2);
    
    cout << amnt << ", " << paid << endl;
    chg = chg + QString("The amount of return is $%1\n").arg(paid-amnt);
    change = (paid-amnt)*100.0;
    

    @

    If I look at the calculation, (paid-amnt)*100.0, the amount is correct, but when this is assigned to the integer "change", something goes wrong. So I am wondering if this is a bug, or if I'm overlooking something in my n00b status.

    Edit: as addition. If I enter amnt=$19.82 and paid=$20, it always calculates "change" to "17"
    If I use $19.83 or $19.81, the amount for "change" is correct to "17" or "19".
    If I enter amnt as $18.82, same thing happens.

    Using QT 4.8.1 for Desktop - MinGW, to compile.

    [Edit: Please use @ tags to wrap code -- mlong] -> OK

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mlong
      wrote on last edited by
      #2

      You have to be careful when using doubles (or floats) to represent money. Both types are inherently imprecise for that purpose and are susceptible to rounding errors internally.

      Software Engineer
      My views and opinions do not necessarily reflect those of anyone -- living or dead, real or fictional -- in this universe or any other similar multiverse node. Void where prohibited. Your mileage may vary. Caveat emptor.

      1 Reply Last reply
      0
      • T Offline
        T Offline
        taeke
        wrote on last edited by
        #3

        I send some variables and calculations to cout, and there things look good:

        19.82, 20
        paid= 20
        amnt= 19.82
        paid-amnt= 0.18
        (paid-amnt)*100= 18
        change= 17

        (change is the result of change = (paid-amnt)*100.0)

        1 Reply Last reply
        0
        • T Offline
          T Offline
          taeke
          wrote on last edited by
          #4

          If I change double to float, the calculation is correct.

          mlong: out of curiosity, if double or floats are imprecise for money, what would one use then instead?

          1 Reply Last reply
          0
          • A Offline
            A Offline
            andre
            wrote on last edited by
            #5

            [quote author="taeke" date="1342722390"]If I change double to float, the calculation is correct.[/quote]
            Perhaps it is for this calculation, but it will be off even more for others.

            Note that you also may just have a problem properly displaying your result.

            [quote]mlong: out of curiosity, if double or floats are imprecise for money, what would one use then instead?[/quote]
            You use "fixed-point arithmatic":http://en.wikipedia.org/wiki/Fixed-point_arithmetic for that. Qt does not support that natively, but there are 3rd party libraries that do support it.

            The idea is that you you basically calculate with integers, but instead of dollars or cents, you let that integer represent (for instance) 1/1000th of a cent. That way, you also get errors in your final calculation, but the size of these errors is known and predictable.

            1 Reply Last reply
            0
            • T Offline
              T Offline
              taeke
              wrote on last edited by
              #6

              Thank you Andre. The suggestion to use integers, was already in the assigment, but I thought it was merely just for ease of calculation. I did a quick search after your post, and understand the issues with rounding errors for financial calculations, is the main reason. IBM etc have special libraries for financial calculations. Interesting topic.

              But, still I wonder why, why the double of 18.0000, when cast to an integer, all of a sudden is 17. I do know that if the double would be 17.9999, this could become 17 when cast to an integer.

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andre
                wrote on last edited by
                #7

                If you think that the result of your calculation was 18.0000, or even if that number can be represented exactly in a floating point number, you did not really understand the problems with floating point math yet[*]. Also, you should understand what casting to a different number type really does. Casting to an int truncates the result. So even if your result is 17.99898298927 or something like that, your cast to int will give your 17, not 18.

                [*] Though, it might be that this number could be represented exactly, not sure. I mean that in general, you cannot assume that any number is represented exactly in a floating point variable.

                1 Reply Last reply
                0
                • T Offline
                  T Offline
                  taeke
                  wrote on last edited by
                  #8

                  I thought I better run the program through the debugger, and it shows clearly what you are saying :) I used a t, where t=paid-amnt. Interesting exercise.

                  @
                  double:
                  amnt 19.82 double
                  paid 20 double
                  t 0.17999999999999972 double
                  change 17 int
                  tmp 0 int

                  float:
                  amnt 19.8199997 float
                  paid 20 float
                  t 0.180000305 float
                  change 18 int
                  tmp 0 int
                  @

                  Thank you Andre!

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    andre
                    wrote on last edited by
                    #9

                    But please: don't change to float because it works in this case. Understand the difference between float and double, and why there may be differences in the results you get. Then, find another way to fix your issue.

                    1 Reply Last reply
                    0
                    • K Offline
                      K Offline
                      koahnig
                      wrote on last edited by
                      #10

                      In addition to Andre's comments, you may want to have a look to rounding "(e.g. qround)":http://qt-project.org/doc/qt-4.8/qtglobal.html#qRound . Just assigning to integers does clipping and not rounding which is of a particular problem. You ran into this with your "pocket money" example above.
                      double (around 16) has more significant digits than a float (around 6). When something like your examples work "better" with float than with double, all alarm bells should ring!!

                      Vote the answer(s) that helped you to solve your issue(s)

                      1 Reply Last reply
                      0
                      • T Offline
                        T Offline
                        taeke
                        wrote on last edited by
                        #11

                        Thank you Koahnig. I solved it by multiplying the amounts straight away by 100, after they are entered, to skip any floating point calculations (which works for this exercise).

                        Topic is closed for me.

                        1 Reply Last reply
                        0

                        • Login

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