## Why Is This Factorial Algorithm Not Accurate

Sorry I feel stupid asking this and am prepared to lose half of my points asking this but why does this algorithm not work? It works up to a point. After the number 13 the factorials are a little off. For instance the numbers do not entirely match in the hundreds thousands place and onward.

```
#include <stdio.h>
float factorial(unsigned int i) {
if (i <= 1) {
return 1;
}
return i * factorial(i - 1);
}
int main() {
int i = 13;
printf("Factorial of %d is %f\n", i, factorial(i));
return 0;
}
```

Here's the output:

```
Factorial of 13 is 6227020800.000000
```

Here is an example of inaccurate output:

```
Factorial of 14 is 87178289152.000000
```

The output for the number 14 should actually be this (from mathisfun.com)

14 87,178,291,200

I changed the return type to float to obtain more accurate output but I obtained this code for the most part from here: https://www.tutorialspoint.com/cprogramming/c_recursion.htm

**EDIT:** If I change to the return type to double the output is accurate up to 21.I am using the *%Lf* string formatter for the output in the *printf* function.

Show source

## Answers ( 5 )

Simple.

`float`

cannot accurately store integers above 16777216 without loss of precision.`int`

is better than float. But try`long long`

so you can properly store 19 digits.There's nothing wrong in your

`algorithm`

as such. It is just that the data types you use have a limit for the highest number they can store. This will be a problem no matter which algorithm you choose. You can change the data types from`float`

to something like`long double`

to hold something bigger. But eventually it will still start failing once the factorial value exceeds the capacity of that data type. In my opinion, you should put an a condition in your factorial function to return without calculating anything if the passed in argument is greater than a value that your chosen datatype can support.`float`

can represent a widerrangeof numbers than`int`

, but it cannot represent all the values within that range - as you approach the edge of the range (i.e., as the magnitudes of the values increase), the gap between representable values gets wider.For example, if you cannot represent values between 0.123 and 0.124, then you also cannot represent values between 123.0 and 124.0, or 1230.0 and 1240.0, or 12300.0 and 12400.0, etc. (of course, IEEE-754 single-precision

`float`

gives you a bit more precision thanthat).Having said that,

`float`

should be able to represent all integer values up to 2^{24}exactly, so I'm going to bet the issue is in the`printf`

call -`float`

parameters are "promoted" to`double`

, so there's a representation change involved, and that may account for the lost precision.Try changing the return type of

`factorial`

to`double`

and see if that doesn't help.<gratuitous rant>Every time I see a recursive factorial function I want to scream. Recursion in this particular case offers no improvement in either code clarity or performance over an iterative solution:

and can in fact result in

worseperformance due to the overhead of so many function calls.Yes, the

definitionof a factorial is recursive, but theimplementationof a factorial function doesn't have to be. Same for Fibonacci sequences. There's even aclosed formsolution for Fibonacci numbersthat doesn't require any looping in the first place.

Recursion's great for algorithms that partition their data into relatively few, equal-sized subsets (Quicksort, tree traversals, etc.). For something like this, where the partitioning is N-1 subsets of 1 element? Not so much.

</gratuitous rant>OP is encountering the precision limits of

`float`

. For typical`float`

, whole number values above`16777216.0f`

arenot allexactly representable.Somefactorial results above this point are exactly representable.Let us try this with different types.

At

`11!`

, the`float`

results exceeds`16777216.0f`

and is exactly correct.At

`14!`

, the`float`

result is imprecise because of limitedprecision.At

`23!`

, the`double`

result is imprecise because of limitedprecision.At

`21!`

, the answer exceeds my`uintmax_t`

range.At

`35!`

, the answer exceeds my`float`

range.At

`171!`

, the answer exceeds my`double`

range.A

stringrepresentation is accurate endlessly until it reaches buffer limitations.Output

Someone posted a similar question a while back. The consensus was if you're writing it for work use a big number library (like GMP) and if it's a programming exercise write up a solution using a character array.

For example: