1

I am trying to write a recursive loop that prints all of the factorials from 1 to 14. I thought everything moved smoothly until I saw the output. What is my mistake?

double i,bounds = 14,factor = 1;

for(i = 0; i <= bounds; i++){
    
    factor = factor * i;
    
    printf("%f          %f", i , factor);
    printf("\n");
    
}

return 0;

The result:

The result

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Taz
  • 21
  • 2

2 Answers2

0

Start your loop at i = 1 otherwise all factors will be 0 as observed. Your implementation is not a recursive loop, just an iterative loop.

#include <stdio.h>

int main() {
    double i = 0, bounds = 14, factor = 1;

    printf("%.0f! = %.0f\n", i, factor);
    for (i = 1; i <= bounds; i++) {
        factor = factor * i;
        printf("%.0f! = %.0f\n", i, factor);
    }
    return 0;
}

Or with a single printf statement:

#include <stdio.h>

int main() {
    double i = 0, bounds = 14, factor = 1;

    for (;;) {
        printf("%.0f! = %.0f\n", i, factor);
        if (i >= bounds)
            break;
        i += 1;
        factor = factor * i;
    }
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
0

Writing recursive functions can be tricky.
That is why a problem like this is, as shown, easily solved with simple iterations.

However, since you asked: "what is my mistake?"
The posted code shows no sign of being a recursive function.
On the other hand, this does:

#include <stdio.h>

double factorial( int n ) {
    double f = 1.0;
    if( n > 1 )
        f = n * factorial( n - 1 ); // here's where Alice goes down the rabbit hole
    printf( "%22.0lf = %2d!\n", f, n ); // and here is where she returns
    return f;
}

int main() {
    factorial( 14 );

    return 0;
}
                     1 =  1!
                     2 =  2!
                     6 =  3!
                    24 =  4!
                   120 =  5!
                   720 =  6!
                  5040 =  7!
                 40320 =  8!
                362880 =  9!
               3628800 = 10!
              39916800 = 11!
             479001600 = 12!
            6227020800 = 13!
           87178291200 = 14!

You can extend this to a few higher values (double's have the capacity), but you will soon encounter errors where there are not enough bits to accurately represent the factorial. Plausible, but wrong, values will be printed.

EDIT
Once you've got the fundamentals working, you can begin to extend the code.

#include <stdio.h>

double factorial( int n ) {
    double f = 1.0;
    if( n > 1 ) f = n * factorial( n - 1 );
    printf( "%13.0lf = %2d! = ", f, n );
    char *pref = "";
    while( n )
        printf( "%s%d", pref, n-- ), pref = "x";
    puts( "" );
    return f;
}

int main() {
    factorial( 15 );

    return 0;
}
            1 =  1! = 1
            2 =  2! = 2x1
            6 =  3! = 3x2x1
           24 =  4! = 4x3x2x1
          120 =  5! = 5x4x3x2x1
          720 =  6! = 6x5x4x3x2x1
         5040 =  7! = 7x6x5x4x3x2x1
        40320 =  8! = 8x7x6x5x4x3x2x1
       362880 =  9! = 9x8x7x6x5x4x3x2x1
      3628800 = 10! = 10x9x8x7x6x5x4x3x2x1
     39916800 = 11! = 11x10x9x8x7x6x5x4x3x2x1
    479001600 = 12! = 12x11x10x9x8x7x6x5x4x3x2x1
   6227020800 = 13! = 13x12x11x10x9x8x7x6x5x4x3x2x1
  87178291200 = 14! = 14x13x12x11x10x9x8x7x6x5x4x3x2x1
1307674368000 = 15! = 15x14x13x12x11x10x9x8x7x6x5x4x3x2x1

(If you blur your eyes and look at that result, you begin to see "the rabbit hole". Odd to realise the 'bottom' of the recursion is the 'top' of that mound.)

EDIT2:
And, once things are in place, there's no end to the variations...

#include <stdio.h>

double factorial( int n ) {
    return ( n == 1 ) ? 1.0 : n * factorial( n - 1 );
}

int main() {
    for( int n = 16; n; n-- ) {
        printf( "%14.0lf = %2d! = ", factorial( n ), n );
        char *pref = "";
        for( int x = 1; x <= n; x++ )
            printf( "%s%d", pref, x ), pref = "x";
        puts( "" );
    }

    return 0;
}
20922789888000 = 16! = 1x2x3x4x5x6x7x8x9x10x11x12x13x14x15x16
 1307674368000 = 15! = 1x2x3x4x5x6x7x8x9x10x11x12x13x14x15
   87178291200 = 14! = 1x2x3x4x5x6x7x8x9x10x11x12x13x14
    6227020800 = 13! = 1x2x3x4x5x6x7x8x9x10x11x12x13
     479001600 = 12! = 1x2x3x4x5x6x7x8x9x10x11x12
      39916800 = 11! = 1x2x3x4x5x6x7x8x9x10x11
       3628800 = 10! = 1x2x3x4x5x6x7x8x9x10
        362880 =  9! = 1x2x3x4x5x6x7x8x9
         40320 =  8! = 1x2x3x4x5x6x7x8
          5040 =  7! = 1x2x3x4x5x6x7
           720 =  6! = 1x2x3x4x5x6
           120 =  5! = 1x2x3x4x5
            24 =  4! = 1x2x3x4
             6 =  3! = 1x2x3
             2 =  2! = 1x2
             1 =  1! = 1

This last example is "wasteful" as it recalculates the result for diminishing values of 'n'. But, it's good to explore alternatives and variations. This last version could be "built into" a calculator program that, for a limited range of integers, simply calculates "n!", returning a single result for display.

The printing functionality could be condensed somewhat, too...

int main() {
    for( int n = 1; n <= 17; n++ ) {
        printf( "%15.0lf = %2d! = ", factorial( n ), n );
        for( int x = 1; x <= n; x++ )
            printf( "%d%c", x, "x\n"[x==n] );
    }
    return 0;
}

EDIT3:
It was suggested that one (or more?) websites and certain arbitrary precision libraries would be the easy out for finding factorials of larger numbers.

Some time ago, I wrote code to generate the nth Fibonacci value. Making absolutely NO claim to the efficiency of this implementation, the alterations to that (shown below) do a reasonable job of finding the factorial for smaller values, and, with patience, this could be extended to run as far as one has time and patience to explore. (It uses a crude form of unpacked BCD and, believe it or not, multiplication by repeated addition. I'm not proud...)

const int targ = 70; // 70!

int main() {
    const int nDigits = 120; // 200 enough?
    uint8_t f[ nDigits ] = { 0 };
    uint8_t a[ nDigits ] = { 0 };
    int soFar = nDigits - 1, n, i;

    f[ soFar ] = 1;
    for( n = 1; n <= targ /*&& getchar()*/; n++ ) {
        int carry, itCnt = 0;

        for( ; itCnt < n; itCnt++ ) {
            carry = 0;
            for( int i = nDigits - 1; i >= soFar || carry; i-- ) {
                a[i] += f[i] + carry;
                a[i] -= "\000\012"[ carry = (a[i] >= 10) ]; // either 0or10 (octal 012)
                soFar -= ( i == soFar && carry ); // extend?
            }
        }

        for( i = 0; i < soFar; i++ ) putchar( ' ' ); 
        for( i = soFar; i < nDigits; i++ ) {
            putchar( '0' + (f[i] = a[i]) );
            a[i] = 0;
        }
        printf( " = %2d!\n", n );
    }

    return 0;
}
                                                                              1 =  1!
                                                                              2 =  2!
                                                                              6 =  3!
                                                                             24 =  4!
                                                                            120 =  5!
                                                                            720 =  6!
                                                                           5040 =  7!
                                                                          40320 =  8!
                                                                         362880 =  9!
                                                            /* omitted for brevity */
                                                                 20922789888000 = 16!
                                                                355687428096000 = 17!
                                                               6402373705728000 = 18!
                                                             121645100408832000 = 19!
                                                            2432902008176640000 = 20!
                                                            /* omitted for brevity */
                                          8683317618811886495518194401280000000 = 33!
                                        295232799039604140847618609643520000000 = 34!
                                      10333147966386144929666651337523200000000 = 35!
                                     371993326789901217467999448150835200000000 = 36!
                                   13763753091226345046315979581580902400000000 = 37!
                                                            /* omitted for brevity */
       230843697339241380472092742683027581083278564571807941132288000000000000 = 54!
     12696403353658275925965100847566516959580321051449436762275840000000000000 = 55!
    710998587804863451854045647463724949736497978881168458687447040000000000000 = 56!
  40526919504877216755680601905432322134980384796226602145184481280000000000000 = 57!
2350561331282878571829474910515074683828862318181142924420699914240000000000000 = 58!
                                                            /* omitted for brevity */
Fe2O3
  • 6,077
  • 2
  • 4
  • 20
  • @SteveSummit The curious student will try this with a single precision "float", and, for those with 64bit compilers, maybe even a "long long"... (I did try higher values of 'n', and yes, recognised I was seeing _plausible_ but **wrong** results...) There's got to be more to this than just spoon-feeding the kids a bunch of answers... `:-)` – Fe2O3 Sep 29 '22 at 22:24
  • 1
    When Alice goes down the rabbit hole shouldn’t see encounter 0! – to be able to correctly calculate wonderful things like the Combinations of n objects taken k at a time? – Verbatim Sep 29 '22 at 22:30
  • @HaveCompiler--WillTravel I'll answer with a quote from Grace Slick: "Go ask Alice..." `:-)` "Feed your head! Feed your head"... – Fe2O3 Sep 29 '22 at 22:31
  • 1
    @Fe2O3 And a fine album it was, too. (And Spencer Elden was in the news recently because of it.) – Steve Summit Sep 29 '22 at 22:45
  • Suggest `n <= 1` as the recursion-breaking condition (and `? n :` to go with it, natch). (Me, I'm not too interested in a "calculator program" that works with a *limited* range of integers; I'm pleased to be able to type, say, `1000!` in a nearby window and confirm the result mentioned at http://catb.org/jargon/html/B/bignum.html .) – Steve Summit Sep 29 '22 at 23:23
  • @SteveSummit Maybe that should be posted as an answer. "Don't reinvent a wonky and probably lop-sided, out-of-balance wheel. Just find-and-use a library function or another language that supplies a _built-in_ facility..." – Fe2O3 Sep 29 '22 at 23:48
  • @SteveSummit "The Jargon File" webpage you mentioned, with the entry for bignum, appears to have a typo -- the webpage shows 1000! with 248 trailing zeroes (instead of 249). The last character is a "dot" instead of a zero. – Verbatim Sep 30 '22 at 01:02
  • @SteveSummit After a day full of distractions, finally polished and posted some (crude) BCD code that you may find interesting.... Let me know when you try it with 1000! Could be Christmas by the time this is done! `:-)` – Fe2O3 Sep 30 '22 at 10:41
  • @Fe2O3 Yes, handrolling tiny, special-purpose multiprecision arithmetic routines, just barely sufficient to answer a given question, is popular sport here on Stack Overflow. See for example [this answer](https://stackoverflow.com/questions/66109785#66110704), and [this question's several answers](https://stackoverflow.com/questions/1384160), and [this one's](https://stackoverflow.com/questions/72013383), and [this somewhat dubious answer](https://stackoverflow.com/questions/69586409#69590952), and [this question](https://stackoverflow.com/questions/70277512). – Steve Summit Sep 30 '22 at 14:53
  • @HaveCompiler--WillTravel Good grief. Thanks for noticing that. I thought I had gotten Eric to fix that, like, 20 years ago. – Steve Summit Sep 30 '22 at 15:08