Pelles C > Bug reports
Factorial Bug
melsmith:
Hi All:
This is my first post.
Environment: C Compiler PellesC64 and running a short Harbour program to test factorial computations.
When running a Factorial function FACT(21), the result is:
51,090,942,171,709,430,000
Other compilers (e.g., Borland BCC 7.4 and MinGW 10.2) show the correct answer should be:
51,090,942,171,709,440,000
The PellesC64 results from FACT(1) thru FACT(20) are *correct* and identical to other compilers. However, FACT(21) is *incorrect*.
-Mel Smith
melsmith:
Hi All:
Simplifying:
The following multiplication is incorrect:
21 * 2432902008176640000 *should be* equal to 51090942171709440000
Instead, Pelles64 produces the result: 51090942171709430000
MinGW 10.1 and BCC 7.4 produce the correct answer.
-Mel
frankie:
--- Quote from: melsmith on June 04, 2020, 08:13:09 PM ---Hi All:
Simplifying:
The following multiplication is incorrect:
21 * 2432902008176640000 *should be* equal to 51090942171709440000
Instead, Pelles64 produces the result: 51090942171709430000
MinGW 10.1 and BCC 7.4 produce the correct answer.
-Mel
--- End quote ---
Such a big number requires a 128bits integer to hold it, or a long double.
In the first case if the Harbour compiler generated a 64bit user you should have experienced an overflow (negative result probably), in the second case, using floats, the different result simply could be due to rounding.
In any case the problem is related to which 'C' types generates the Harbour compiler with different back-end C-compilers.
I suggest you to ask the question on the Harbour forum.
Personally I'll be glad if you'll share the naswer with us. ;)
Pelle:
Oh joy, binary floating-point. My favorite subject. Not!
Well, if I try this code...
--- Code: ---#include <stdio.h>
double tail_recursive_factorial_aux(double n, double acc) {
return n < 1 ? acc : tail_recursive_factorial_aux(n - 1, acc * n);
}
double tail_recursive_factorial(double n) {
return tail_recursive_factorial_aux(n, 1);
}
int main(void) {
for (double n = 1; n < 25; n++) {
union {
double d;
unsigned char b[8];
} u;
u.d = tail_recursive_factorial(n);
printf("%3.0f! = %40.15f - 0x%02hhX:0x%02hhX:0x%02hhX:0x%02hhX:0x%02hhX:0x%02hhX:0x%02hhX:0x%02hhX\n", n, u.d, u.b[7], u.b[6], u.b[5], u.b[4], u.b[3], u.b[2], u.b[1], u.b[0]);
}
}
--- End code ---
... the output looks a bit better with MSVC (Version 19.25.28614 for x64) than with Pelles C (I tried v10.0, but whatever).
For stuff like this I use the C runtime by P.J. Plauger, Dinkumware.
A quick web search turned up this, and little else:
https://github.com/Justme0/CLIB
This version (possibly unlicenced) is older than my version (which I bought many years ago). For example no C99 support like %a, but for the printf("%f", ...) case the code looks the same.
In the STDIO folder, the files forming the call chain for printf("%f", ...) looks like:
PRINTF.C -> XPRINTF.C -> XPUTFLD.C -> XLDTOB.C -> XGENLD.C
where the most interesting part is probably a loop in XLDTOB.C forming a sequence of "ASCII" digits. I can't immediately figure out if there is a reasonably easy way to improve the code/precision.
Does anyone here feels like more of an expert on this...?
melsmith:
Hi Pelle and Frankie:
I'll return to my xHarbour ng, and report your comments to the poster who complained..
Thanks for the response(s).
-Mel Smith
(a 'Repositarian' for the Harbour Language)
www.whosaway.com
Navigation
[0] Message Index
[#] Next page
Go to full version