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.