Omnimaga

General Discussion => Technology and Development => Computer Programming => Topic started by: Munchor on June 16, 2011, 05:38:03 pm

Title: Factorial Output
Post by: Munchor on June 16, 2011, 05:38:03 pm
I was trying to make a C Program that returns the factorial of a given number without using any libraries (besides stdio.h).

Code: [Select]
#include <stdio.h>

int main();
int factorial(int n);

int main() {
   
    int n;
   
    scanf("%d",&n);
   
    int i;
    for (i=0;i<n;i++)
    {
        int x;
        scanf("%d",&x);
        printf("%i\n",factorial(x));
    }
   
    return 0;
}

int factorial(int n)
{
    if (n==0)
    {
        return 1;
    }
    int sum = 1;
    int i;
    for (i=n;i>0;i--)
    {
        sum = sum*i;
    }
    return sum;
}

That's my code, the first line of input is supposed to be the number of inputs. Then for each input I output its factorial.

It works fine for me. However, this (https://www.spoj.pl/problems/FCTRL2/) won't accept it. Any ideas?
Title: Re: Factorial Output
Post by: Juju on June 16, 2011, 05:45:33 pm
You should replace
Code: [Select]
printf("%i",factorial(x));with
Code: [Select]
printf("%i\n",factorial(x));
You forgot the newlines.

EDIT: Ninja'd?
Title: Re: Factorial Output
Post by: calc84maniac on June 16, 2011, 06:06:04 pm
The numbers are getting way too big. You'd have to use some sort of arbitrary-precision math or something (considering it can go up to 100!)
Title: Re: Factorial Output
Post by: DrDnar on June 16, 2011, 11:24:24 pm
Try using doubles. Integers will definitely not go up to the factorial of 100, which has 157 digits. You'll lose precision in the lower digits, but that may not be not important.
Title: Re: Factorial Output
Post by: Juju on June 17, 2011, 12:06:34 am
Doubles will definitively do the job. 32-bit integers will only hold up to 12!, while 64-bit will hold up to 20!. Doubles will hold up to 170!.

Note that 100! = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000.
Title: Re: Factorial Output
Post by: Builderboy on June 17, 2011, 12:25:28 am
Ah, doubles will hold numbers as large as 170! but will you get all of the decimal precision?  I think not, if I remember correctly the double in C only allows for around 16 decimal digits
Title: Re: Factorial Output
Post by: Juju on June 17, 2011, 12:28:51 am
52 bits of precision's not enough indeed. You might want to try binary-coded decimal (BCD) and figure out how to multiply stuff in BCD.

I did some BCD in Axe today to hold up to a lot of digits.
Title: Re: Factorial Output
Post by: calc84maniac on June 17, 2011, 12:33:23 am
Or it might be even easier to just store individual digits in an array (even though that wastes a little bit of space).
Title: Re: Factorial Output
Post by: Juju on June 17, 2011, 12:35:40 am
Yeah, same principle as BCD. You have to store each digit separately and figure out multiplication with that.
Title: Re: Factorial Output
Post by: DrDnar on June 17, 2011, 12:38:38 am
That may or may not be faster depending on CPU design, memory bandwidth, caching, integer size, et cetera. If you have high-latency memory, BCD may well make things much faster, as the code for screwing with the individual nibbles could be faster than the penalty for a cache miss.

The Z80 has instructions for helping with BCD a little, namely the DAA instruction. You might consider making an Axiom of a generic open source BCD library.
Title: Re: Factorial Output
Post by: calc84maniac on June 17, 2011, 12:39:45 am
That may or may not be faster depending on CPU design, memory bandwidth, caching, integer size, et cetera. If you have high-latency memory, BCD may well make things much faster, as the code for screwing with the individual nibbles could be faster than the penalty for a cache miss.

The Z80 has instructions for helping with BCD a little, namely the DAA instruction. You might consider making an Axiom of a generic open source BCD library.
I'm talking about Scout's C program ;)
Title: Re: Factorial Output
Post by: DrDnar on June 17, 2011, 12:41:24 am
Yeah, I first addressed, that, and the I addressed the BCD in Axe. I'm assuming that Scout is coding for a PC, and I thought that it might be worth pointing out that there are performance considerations in which you choose.
Title: Re: Factorial Output
Post by: AngelFish on June 17, 2011, 12:41:25 am
Ah, doubles will hold numbers as large as 170! but will you get all of the decimal precision?  I think not, if I remember correctly the double in C only allows for around 16 decimal digits

If it's an integer data type, then yes. A double floating point number will not have the precision, though. As for BCD...

Anyone who uses BCD for any reason other than ease of use should be shot :P
You get all the precision of a floating point number with a little more than half the space efficiency.

If you need to operate on large numbers without math.h, then I recommend using arrays to store your numbers. 100! takes up 66 bytes in integer format, so a custom routine that malloc's an array and then applies the operations to that array will be able to represent massive numbers with no loss of precision. You'll also likely want to improve that algorithm with numbers like 100! :P
Title: Re: Factorial Output
Post by: calc84maniac on June 17, 2011, 12:43:52 am
Ah, doubles will hold numbers as large as 170! but will you get all of the decimal precision?  I think not, if I remember correctly the double in C only allows for around 16 decimal digits

If it's an integer data type, then yes. A double floating point number will not have the precision, though. As for BCD...

Anyone who uses BCD for any reason other than ease of use should be shot :P
You get all the precision of a floating point number with a little more than half the space efficiency.

If you need to operate on large numbers without math.h, then I recommend using arrays to store your numbers. 100! takes up 66 bytes in integer format, so a custom routine that malloc's an array and then applies the operations to that array will be able to represent massive numbers with no loss of precision. You'll also likely want to improve that algorithm with numbers like 100! :P
I recommend storing in decimal because he's going to have to output the values in human-readable format. I assume he won't want to make a routine to extract decimal digits from a large binary number.
Title: Re: Factorial Output
Post by: Juju on June 17, 2011, 12:46:05 am
Well yeah. You have to store each decimal digit separately and allow for a seemingly infinite number of digits. That's how BCD works, kinda.
Title: Re: Factorial Output
Post by: AngelFish on June 17, 2011, 12:58:22 am
I recommend storing in decimal because he's going to have to output the values in human-readable format. I assume he won't want to make a routine to extract decimal digits from a large binary number.

It's not terribly difficult to convert to decimal, but yeah.

Example psuedo-code for Hex array->Dec:
Code: [Select]
int arraysize;
char *array;
char *output;
int j = 0;
For(i,i<arraysize,i++) {
stream = *array[i];

if stream>0x0A {
*array[j] = 0x31;
j = j+1;
stream = stream % 10;
}
*array[j] = stream + 0x30;
j = j+1;
}
Title: Re: Factorial Output
Post by: calc84maniac on June 17, 2011, 01:02:38 am
I recommend storing in decimal because he's going to have to output the values in human-readable format. I assume he won't want to make a routine to extract decimal digits from a large binary number.

It's not terribly difficult to convert to decimal, but yeah.

Example psuedo-code for Hex array->Dec:
Code: [Select]
int arraysize;
char *array;
char *output;
int j = 0;
For(i,i<arraysize,i++) {
stream = *array[i];

if stream>0x0A {
*array[j] = 0x31;
j = j+1;
stream = stream % 10;
}
*array[j] = stream + 0x30;
j = j+1;
}
That's assuming each byte holds a value from 0-99 (or 0x00 to 0x63 if you prefer). Binary numbers are in base 2, not base 100.
Title: Re: Factorial Output
Post by: AngelFish on June 17, 2011, 01:26:46 am
Actually, it assumes a value from 0x0 to 0xF, which just proves that BCD is better  :P
Title: Re: Factorial Output
Post by: calc84maniac on June 17, 2011, 01:29:11 am
Oh yeah, cause when you display 0xFFFF, it turns out as 15151515! Nice to know :D
Title: Re: Factorial Output
Post by: Munchor on June 17, 2011, 03:00:26 am
I see everyone, I tried this:

Code: [Select]
#include <stdio.h>

int main();
double factorial(int n);

int main() {
   
    int n;
   
    scanf("%d",&n);
   
    int i;
    for (i=0;i<n;i++)
    {
        int x;
        scanf("%d",&x);
        printf("%f\n",factorial(x));
    }
   
    return 0;
}

double factorial(int n)
{
    if (n==0)
    {
        return 1;
    }
    double sum = 1;
    int i;
    for (i=n;i>0;i--)
    {
        sum = sum*i;
    }
    return sum;
}

But it returns "inf" for all numbers :/
Title: Re: Factorial Output
Post by: AngelFish on June 17, 2011, 03:09:23 am
Well, you're not declaring x to be anything but null, so..
Title: Re: Factorial Output
Post by: Munchor on June 17, 2011, 09:16:15 am
Well, you're not declaring x to be anything but null, so..

Oh I see, but I also tried this and get the same output:

Code: [Select]
#include <stdio.h>

int main();
double factorial(double n);

int main() {
   
    int n;
   
    scanf("%d",&n);
   
    int i;
    for (i=0;i<n;i++)
    {
        double x;
        scanf("%lf",&x);
        printf("%lf\n",factorial(x));
    }
   
    return 0;
}

double factorial(double n)
{
    if (n==0)
    {
        return 1;
    }
    double sum = 1;
    int i;
    for (i=n;i>0;i--)
    {
        sum = sum*i;
    }
    return sum;
}
Title: Re: Factorial Output
Post by: Builderboy on June 17, 2011, 10:17:09 am
He means you are not initializing X with a value, you are just going int X or double X, which creates the variable, but it holds no value.
Title: Re: Factorial Output
Post by: calc84maniac on June 17, 2011, 11:23:15 am
And both of you seem to be missing the scanf() with argument of &x.
Title: Re: Factorial Output
Post by: Munchor on June 17, 2011, 11:27:17 am
He means you are not initializing X with a value, you are just going int X or double X, which creates the variable, but it holds no value.

Code: [Select]
double x;
scanf("%lf",&x);

I get it through input.
Title: Re: Factorial Output
Post by: Munchor on June 18, 2011, 04:09:36 pm
Bump anybody?
Title: Re: Factorial Output
Post by: Belberith on July 11, 2011, 02:46:57 pm
Try this? It's just a different method of calculating the factorial.

Code: [Select]
#include <stdio.h>

int main();
double factorial(double n);

int main() {
   
    int n;
   
    scanf("%d",&n);
   
    int i;
    for (i=0;i<n;i++)
    {
        double x;
        scanf("%lf",&x);
        printf("%lf\n",factorial(x));
    }
   
    return 0;
}

double factorial(double n)
{
    if ((n == 1) || (n == 0))
    {
        return(1);
    }
    else
    {
        return(n * factorial(n - 1));
    }
}