Programming Arduino to do Factorials

Hi, I just started very basic Arduino programming this last week in class, and I’m having trouble with a project. We’re supposed to program Arduino to compute factorials from 0 to 10 and spit out the info like this:

"
The factorial of 0 is 1

The factorial of 1 is 1

The factorial of 2 is 2

The factorial of 3 is 6
"

This is the code I’ve put in:
"int n, m;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
n = 1;
m = 10;

int fact = 1;
for(int x = n; x <= m; x++)
{
fact = fact * x;
Serial.print("The Factorial of “);
Serial.print(x);
Serial.print(” is ");
Serial.println(fact);
delay(1000);
}

}
"

I’ve made progress to be able to compute factorials up to 7!, but once I hit 8 it gets weird. This is what I’m getting from the Serial Monitor:

"
The Factorial of 1 is 1
The Factorial of 2 is 2
The Factorial of 3 is 6
The Factorial of 4 is 24
The Factorial of 5 is 120
The Factorial of 6 is 720
The Factorial of 7 is 5040
The Factorial of 8 is -25216
The Factorial of 9 is -30336
The Factorial of 10 is 24320
The Factorial of 1 is 1
The Factorial of 2 is 2
The Factorial of 3 is 6
The Factorial of 4 is 24
[etc.]
"

Can someone help me understand why this is? Thanks for all suggestions and advice!

BTW, I’m pretty sure I know how to include 0!, I’ll do that at the end.

You're overflowing the int. An int can only go from -32767 to +32767 on most Arduinos.

Since 10! is about 3.6 million, you will need to set fact to an unsigned long.

saximus:
You're overflowing the int. An int can only go from -32767 to +32767 on most Arduinos.

Since 10! is about 3.6 million, you will need to set fact to an unsigned long.

@saximus
Hey, that did it, it works perfectly now, thanks!

Would you be able to explain just what was going wrong though? What does it mean to overflow the int and why was that happening. Thanks!

A "byte" only uses one byte (8 bits), and can therefore only hold 256 values.

An "int" uses two bytes (65,536 values), but one of the bits is used as a sign bit.
So you can have negative numbers.
But that also halves the possible positive values.

So if you don't need negative values, then use "unsigned int".

Same story for "long" and "unsigned long".
Both are using four bytes.

https://www.arduino.cc/en/Reference/Int

https://www.arduino.cc/en/Reference/UnsignedLong
Leo..

To add to what Wawa wrote, it helps me to visualise what is going on. If you're on a Windows computer, the built in calculator does a really good job of doing that. You can click individual bits to flip them and play around with the different bases.

If you're familiar with different number bases and conversion, you would know that 0111 1111 1111 1111 is equal to 32767 and that if you add 1 to that you get 1000 0000 0000 0000 which equals 32768. However, when you're talking about signed 16-bit integers, that number actually equals -32768 because the most significant bit is used to indicate that the number is negative rather than being used to add to the value. There is also some special maths required once you're talking about negatives but I don't understand that well enough to try to explain it.

For your first "incorrect" value, 8!, the numerical value is 40,320. The binary representation of that number is 1001 1101 1000 0000 but now we know that first 1 tells the microcontroller that it should be negative. So, when you do the funky maths required to convert it, you find that the binary number actually represents -25216.

You can see this on Windows Calculator by choosing decimal base and "QWord" or "DWord". Enter 40320 and then choose "Word" (this is the equivalent of a signed int on Arduino). Your 40320 instantly switches to -25216