Lord.of.AMC's blog

By Lord.of.AMC, 9 years ago, In English

I have the following code:

#include <iostream>
#include <vector>
using namespace std;
 
int v[2];
 
int main()
{
    double p;
    cin >> p;
    v[0] = p*10;
    cout << v[0] << endl;
}

When I input "2.3" into the program on my computer it gives the expected result, 23. But when I input 2.3 on Codeforces and run it, I get 22. Any reason why?

  • Vote: I like it
  • -20
  • Vote: I do not like it

»
9 years ago, # |
  Vote: I like it +8 Vote: I do not like it

Because that is how floating point numbers work. See this: https://gcc.gnu.org/bugs/#nonbugs_general

  • »
    »
    9 years ago, # ^ |
      Vote: I like it -13 Vote: I do not like it

    Can you please describe how that is not a bug? How does rounding affect such a simple operation? :S

    • »
      »
      »
      9 years ago, # ^ |
        Vote: I like it +6 Vote: I do not like it

      Consider the following program:

      #include <cstdio>
      using namespace std;
      
      int main()
      {
          double p;
          scanf("%lf",&p);
          printf("%.20lf\n",p);
      }
      

      When you input 2.3 you get output 2.29999999999999980000. This is because 2.3 cannot be exactly represented as a binary number, so rounding occurs. When multiplied by 10 it is slightly less then 23 (22.9....). Now convertion to int works by just throwing away the fractional part and you get 22 as a result.

      • »
        »
        »
        »
        9 years ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        Can you explain why the following code gives the answer = 23? Thanks!

        #include <iostream>
        #include <cstdio>
        using namespace std;
         
        int main(){
            double p = 2.3;
            int v = p*10;
            cout << v << endl;
            return 0;
        }
        
        • »
          »
          »
          »
          »
          9 years ago, # ^ |
            Vote: I like it +3 Vote: I do not like it

          In this case compiler (at least g++ 4.9.1) optimizes your code, excluding variables p and v as they are not used anywhere else except cout. So, compiler multiplies 2.3 by 10 itself and does it in a precise way. Practically, after optimization, your code looks like this:

          int main() { 
            cout << 23 << endl;
            return 0;
          }
          

          You can look into assembler codes generated by some compilers here: http://gcc.godbolt.org/

»
9 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Use v[0] = p*10 + 1e-9; instead and you will get 23. Even better, use v[0] = p*10 + 0.5 which will convert to the nearest integer. Always account for rounding errors, when you convert from double to int.