Pelles C > Bug reports

Factorial Bug

(1/3) > >>

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