bug with adding numbers with unsigned long long var

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • jures
    New Member
    • Oct 2013
    • 2

    bug with adding numbers with unsigned long long var

    Code:
    ...
    #include <cmath>
    ...
    
    
    unsigned long long X, j , i, total = 0;
    cin >> X;
    
    
    for ( i = 0 ; i < 18 ; ++i )
    {
        total += 9*(i+1)*pow(10,i);
        //cout << "total : " << total << endl;
        if ( total >= X ) break;
        }
    
    cout << total ;
    For input 40000 it gives me wrong answer. It should be 488889, but result is 488887. Also with input 3000 gives wrong thing. I'm working on Windows, code blocks and it doesn't work when I put g++ follow C++11 standard ( in settings -> compiler ). Warning is that ISO C++ 1998 does not support long long. Anybody can help me with this ? ty :)
  • Nepomuk
    Recognized Expert Specialist
    • Aug 2007
    • 3111

    #2
    Hi jures and welcome to bytes.com!

    I just checked my local g++ installation and it doesn't seem to support the C++11 standard; C++98 seems to be the closest I can get. Compiling with that I had to change a few things as the pow function isn't defined for an int and a long long value. Here's what I came up with:
    [code=c++]#include<cmath>
    #include<iostre am>

    using namespace std;

    int main() {
    unsigned long long X, j, total = 0;
    int i;
    cin >> X;

    for ( i = 0 ; i < 18 ; ++i ) {
    total += 9*(i+1)*pow(10. ,i);
    //cout << "total : " << total << endl;
    if ( total >= X ) break;
    }

    cout << total << endl;
    }
    [/code] You will notice two slight differences to your code: i is an int rather than an unsigned long long and the first argument of that pow function is now a double value (due to the point after the digits). This not only compiles but for the input 40000 it indeed returns 488889 as you expect. If I take out the commented line, the output is as follows:
    Code:
    total : 9
    total : 189
    total : 2889
    total : 38889
    total : 488889
    488889
    So, the question is: Does that code work for you and if not, where does it go wrong?

    Comment

    • jures
      New Member
      • Oct 2013
      • 2

      #3
      oh , I see :D
      meanwhile, I lost my temper and just installed older version and it works with long long. Yes, code works exactly as I wish. Ty :)

      Comment

      • Nepomuk
        Recognized Expert Specialist
        • Aug 2007
        • 3111

        #4
        An older version works while a newer one doesn't? What a weird world we live in... ;-)

        Comment

        • donbock
          Recognized Expert Top Contributor
          • Mar 2008
          • 2427

          #5
          Use of floating-point always carries the risk of imprecise results. @Nepomuk has shown that this doesn't have to be the case in your specific case; but the general point remains: use floating point if you have to but always consider if you can manage with integers.

          You can replace the pow() function like this:
          Code:
          long long multiplier = 1;
          ...
          for ( i = 0 ; i < 18 ; ++i ) {
             total += 9*(i+1)*multiplier;
             multiplier *= 10;
             //cout << "total : " << total << endl;
             if ( total >= X ) break;
          }
          This change has two benefits: you eliminate any chance of imprecision introduced by floating point arithmetic; and your code will run faster.

          Comment

          Working...