fonmagnus's blog

By fonmagnus, history, 2 months ago, In English

Last night I worked on this problem on Codeforces round 823 1730B - Meeting on the Line

I've made two submissions :

  1. Wrong answer on test 3 — 173469198
  2. Accepted — 173524856

The accepted one using a setprecision function while the wrong answer one is not

After I take a look at the cause, then it stumbles upon this following message from checker : wrong answer 36th numbers differ - expected: '40759558.0000000', found: '40759600.0000000', error = '0.0000010'

How come the difference becomes very large? I know floating point has its own "weaknesses" for handling precision and stuff, but how come the difference of using "setprecision" and not using them produce a very different outcome?

Appreciate for the answers because I'm curious. Thanks!

 
 
 
 
  • Vote: I like it
  • +7
  • Vote: I do not like it

»
2 months ago, # |
Rev. 2   Vote: I like it +18 Vote: I do not like it

it's not floating point precision, it's the way the number is printed. When double gets sufficiently large, C++ automatically prints it in scientific notation, and that's when you run into the problems you had. Just check what your code is outputting

»
2 months ago, # |
Rev. 2   Vote: I like it +18 Vote: I do not like it

It is precisely what you might expect, the float wasn't printed to a large enough precision. The default, is unluckily 6. Just one less than what would be sufficient for an AC. 40759558 is rounded up to 40759600 when you consider 6 digits of precision, which is insufficient.

You might be mistaking setprecision() for the precision of the floating point calculations, however it sets how many digits are printed in cout when printing a decimal type. The precision of the calculation is determined by the decimal datatype you use.

»
2 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Wow thanks for making this post. I ran into exactly the same issue being unable to figure it out.

»
2 months ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

For standard streams, the floatfield format flag is set to defaultfloat on initialization. When floatfield is set to defaultfloat, floating-point values are written using the default notation: the representation uses as many meaningful digits as needed up to the stream's decimal precision (precision), counting both the digits before and after the decimal point (if any).

When floatfield is set to fixed, floating-point values are written using fixed-point notation: the value is represented with exactly as many digits in the decimal part as specified by the precision field (precision) and with no exponent part.

References: link1, link2

So, it wasn't setprecision that got your solution accepted, it was fixed. As default precision is set to 6, cout << fixed << (mn+mx)/2.0 << endl; also gets accepted (for this problem).

»
2 months ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

Same happened to me I was also confused for hours.

»
2 months ago, # |
  Vote: I like it 0 Vote: I do not like it
  • »
    »
    2 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Your cout << fixed etc line is after solve(). If you put it before your code will get AC.

  • »
    »
    2 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Use fixed and setprecision on the same line where you are printing x. like here I used in your code.

»
2 months ago, # |
  Vote: I like it 0 Vote: I do not like it

I was also doing the same mistake lol. Lastly, I did something like this

if (fans % 2 == 1) {
    fans /= 2;
    cout << fans << ".5\n";
    return;
}

fans /= 2;
cout << fans << "\n";
»
2 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Damn it I made the same mistake and get stuck at the same place. I did not correct it until the contest ended.