-2

I ran the following 2 snippets of code on the same set of inputs, which are the same except the usage of "namespace std" in the second. I am not able to understand the reason why their outputs are different. Can someone please guide me? Thanks!

Program 1:

#include<cmath>
#include<cstdio>
//using namespace std;
int main() {
    int i, p, q, r, s;
    while (scanf("%d %d %d %d", &p, &q, &r, &s) == 4) {
        long double ans = 0;
        if (p - q < q)
            q = p - q;
        if (r - s < s)
            s = r - s;
        for (i = 1; i <= q; i++)
            ans += log(p - q + i) - log(i);
        for (i = 1; i <= s; i++)
            ans -= log(r - s + i) - log(i);
        printf("%.5lf\n", exp(ans));
    }
    return 0;
}

Output 1:

0.12587
505606.46055
1.28223
0.48996
2.00000
3.99960

http://ideone.com/x7n5cm

Program 2:

#include<cmath>
#include<cstdio>
using namespace std;
int main() {
    int i, p, q, r, s;
    while (scanf("%d %d %d %d", &p, &q, &r, &s) == 4) {
        long double ans = 0;
        if (p - q < q)
            q = p - q;
        if (r - s < s)
            s = r - s;
        for (i = 1; i <= q; i++)
            ans += log(p - q + i) - log(i);
        for (i = 1; i <= s; i++)
            ans -= log(r - s + i) - log(i);
        printf("%.5lf\n", exp(ans));
    }
    return 0;
}

Output 2:

0.00000
0.00000
0.00000
0.00000
0.00000
0.00000

http://ideone.com/meDkRh

input:

10 5 14 9
93 45 84 59
145 95 143 92
995 487 996 488
2000 1000 1999 999
9998 4999 9996 4998

Edits: 1) replaced #include "bits/stdc++.h" with standard headers. 2) replaced images with actual pieces of code.

piyukr
  • 631
  • 3
  • 12
  • 18
  • 3
    [Get rid of the `` stuff](http://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h?noredirect=1&lq=1) and include the proper headers, so that we have a standard C++ program that can be properly analyzed. – PaulMcKenzie Mar 11 '17 at 06:46
  • @PaulMcKenzie made the edit as suggested, the problem still persists. – piyukr Mar 11 '17 at 07:00
  • The overloaded functions of [`double log()`](http://www.cplusplus.com/reference/cmath/log/) for integral types (suspected by ildjarn) cast the argument to `double` before doing the logarithm. I checked this in [ideone](http://ideone.com/cLSQqK) (out of curiosity). Hmm. Could the propagation from `double` to `long double` (in `operator += ()`) cause the behavior? – Scheff's Cat Mar 11 '17 at 07:31
  • @Scheff I checked if operator += was causing this behaviour. It seems unlikely as the value of ans is the same in both cases. See http://ideone.com/NYl5VD http://ideone.com/uwRGLg – piyukr Mar 11 '17 at 07:48
  • 2
    @piyukr I believe the correct formatting in `printf` would be [`"%.5Lf"`](http://www.cplusplus.com/reference/cstdio/printf/?kw=printf). You see that stream operators really have advances. – Scheff's Cat Mar 11 '17 at 07:54
  • 1
    With no offense, why is the question getting downvotes? Is the answer so obvious that it does not deserve a question or am I not putting in enough effort, with the guidance I am getting, to research the problem here? – piyukr Mar 11 '17 at 08:11
  • 2
    Posting images of code is frowned upon. Post code, not pictures. – Christian Hackl Mar 11 '17 at 09:57
  • 2
    @piyukr: What kept you from copying the output with CTRL+C? And even if it were true that ideone.com prevented you from copying the output as text (which it does not), that would still not mean that you couldn't copy and paste your own source code as text. – Christian Hackl Mar 11 '17 at 10:16
  • 1
    The answer below successfully presented the code as text instead of images. There is almost no excuse for typing the code instead of posting images. – rlam12 Mar 11 '17 at 10:22
  • @ChristianHackl Replaced the images with actual code. Thanks for the suggestion. – piyukr Mar 11 '17 at 10:31
  • 1
    @piyukr: I removed my downvote. – Christian Hackl Mar 11 '17 at 10:49

1 Answers1

2

After fiddling around with the log() and suspecting the operator += () I finally solved this puzzle.

The actual error is caused by printf("%.5lf\n", ...).

I modified the sample code slightly to demonstrate:

#include<cmath>
#include<cstdio>
#include<iomanip>
#include<iostream>
using namespace std;
int main() {
    int i, p, q, r, s;
    while (scanf("%d %d %d %d", &p, &q, &r, &s) == 4) {
        long double ans = 0;
        if (p - q < q)
            q = p - q;
        if (r - s < s)
            s = r - s;
        for (i = 1; i <= q; i++)
            ans += log(p - q + i) - log(i);
        for (i = 1; i <= s; i++)
            ans -= log(r - s + i) - log(i);
        printf("printf: %.5lf", exp(ans));
        cout << "\tcout: " << fixed << setprecision(5) << exp(ans) << endl;
    }
    return 0;
}

The output is now:

printf: 0.00000 cout: 0.12587
printf: 0.00000 cout: 505606.46055
printf: 0.00000 cout: 1.28223
printf: 0.00000 cout: 0.48996
printf: 0.00000 cout: 2.00000
printf: 0.00000 cout: 3.99960

I checked this on ideone. The same output I get when I compile and run this with VS2013 on Windows 10 (64 bit).

I checked this also with gcc in cygwin on Windows 10 (64 bit) and got the following output:

$ g++ -std=c++11 -o test-longdouble test-longdouble.cc ; echo '10 5 14 9
> 93 45 84 59
> 145 95 143 92
> 995 487 996 488
> 2000 1000 1999 999
> 9998 4999 9996 4998
> ' | ./test-longdouble
printf: -0.00000        cout: 0.12587
printf: -4234002535919089587818586571373347278663379000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000        cout: 505606.46055
printf: -0.00000        cout: 1.28223
printf: -65094314467486612925155033958017324735054040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000     cout: 0.48996
printf: nan     cout: 2.00000
printf: nan     cout: 3.99960

$ g++ -std=c++14 -o test-longdouble test-longdouble.cc ; echo '10 5 14 9
93 45 84 59
145 95 143 92
995 487 996 488
2000 1000 1999 999
9998 4999 9996 4998
' | ./test-longdouble
printf: -0.00000        cout: 0.12587
printf: -4234002535919089587818586571373347278663379000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000        cout: 505606.46055
printf: -0.00000        cout: 1.28223
printf: -65094314467486612925155033958017324735054040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000     cout: 0.48996
printf: nan     cout: 2.00000
printf: nan     cout: 3.99960

$ g++ --version
g++ (GCC) 5.4.0

I didn't see it at the first glance but cout output is correct, only the printf output is different.

Considering that the printf formatter is chosen wrong you should not have any expectations about its effect.

Then I fixed the wrong formatting in printf():

#include<cmath>
#include<cstdio>
#include<iomanip>
#include<iostream>
using namespace std;
int main() {
  int i, p, q, r, s;
  while (scanf("%d %d %d %d", &p, &q, &r, &s) == 4) {
    long double ans = 0;
    if (p - q < q)
      q = p - q;
    if (r - s < s)
      s = r - s;
    for (i = 1; i <= q; i++)
      ans += log(p - q + i) - log(i);
    for (i = 1; i <= s; i++)
      ans -= log(r - s + i) - log(i);
    printf("printf: %.5Lf", exp(ans));
    cout << "\tcout: " << fixed << setprecision(5) << exp(ans) << endl;
  }
  return 0;
}

Compiled and tested again with gcc in cygwin on Windows 10 (64 bit):

$ g++ -std=c++14 -o test-longdouble test-longdouble.cc ; echo '10 5 14 9
93 45 84 59
145 95 143 92
995 487 996 488
2000 1000 1999 999
9998 4999 9996 4998
' | ./test-longdouble
printf: 0.12587 cout: 0.12587
printf: 505606.46055    cout: 505606.46055
printf: 1.28223 cout: 1.28223
printf: 0.48996 cout: 0.48996
printf: 2.00000 cout: 2.00000
printf: 3.99960 cout: 3.99960

Thus, I can only repeat what I already stated in my comment: You really should use C++ stream output. printf() can cause weird behavior due to the slightest mistakes in formatters.

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
  • your code worked fine on ideone. However when I ran on my computer, the output was incorrect. See http://imgur.com/a/Gxw9Q – piyukr Mar 11 '17 at 08:05
  • @piyukr OK. In your code, you did not use standard headers. Could this explain different behavior? – Scheff's Cat Mar 11 '17 at 08:32
  • Sorry, it was a mistake. I ran the program again, this time with the standard headers. See http://imgur.com/a/MwFs6 – piyukr Mar 11 '17 at 08:37
  • 1
    @piyukr I did it on cygwin and get the same rubbish. So what? I tried `-std=c++11` and `-std=C++14`. No difference. My gcc version: 5.4.0. The one in ideone: 6.3. Could this be the difference? – Scheff's Cat Mar 11 '17 at 08:40
  • 1
    @piyukr I tested this also with VS2013 (partly C++11, Windows 10, 64 bit). There it works like stated in my answer. Did we uncover a bug in gcc < 6.3 (or the according standard libraries)? – Scheff's Cat Mar 11 '17 at 08:57
  • @piyukr Did you reallize that only the `printf` output was screwed? After scrolling I saw that `cout` was correct in all cases. – Scheff's Cat Mar 11 '17 at 09:10
  • http://imgur.com/a/MwFs6 I am not able to understand why am I getting incorrect output for both cout and printf("%.5LF",exp(ans)); here. I am using MINGW 6.3. – piyukr Mar 11 '17 at 09:29
  • @piyukr No idea. Did you try this with `double` instead of `long double`? Where got you the libraries from? (May be they are compiled with wrong settings.) I really have no idea. Everything, I used for tests in my answer was "out of the box" i.e. ready binaries installed. (I'd like to leave compiling libraries to the professionals which hopefully know what they do.) – Scheff's Cat Mar 11 '17 at 15:26