unsigned long int versus int calculation enigma

Following code makes the correct calculation (result must be 480):

unsigned long int test;
unsigned long int a=50;
unsigned long int b=40;
unsigned long int c=200;

void setup() {
  Serial.begin(115200);
}

void loop() {
  test=a*b*60*8/10/c; // correct result must be 480
  Serial.print(F("test = "));
  Serial.println(test);
  delay(1000);
}

However,

  1. when a & b are int and c is unsigned long int the result is wrong (152)
  2. when a & c are int and b is unsigned long int the result is correct
  3. when b & c are int and a is unsigned long int the result is correct
  4. when a & b & c are int the result is wrong (152)

What is the logic?

An int is 16 bits on most Arduino and can hold numbers between about -32,000 and +32,000 if signed and 0 to 65,000 if unsigned.

A long int is 32 bits and can hold very much larger numbers. Can't hold negative numbers if unsigned.

In your formula

test=a*b*60*8/10/c;

all the operators (/ and *) are equal precedence, so should be evaluated in strict left-to-right order.

When you use a literal value like "80", this is treated as an int. If you want it to be treated as a long int, you need to put "80L".

If the calculation starts with an int, it will stay as an int until it meets a long int. At that point, the rest of the calculation gets done as long int. But if, while the calculation is done as int, it exceeds the limits of int, the calculation will go wrong.

If you re-write your formula like this

test=8L*a*b*60/10/c;

it will start as a long int and stay that way, so should be correct whatever types a, b & c are.

PaulRB:
An int is 16 bits long on most Arduino and can hold numbers between about -32,000 and +32,000 if signed and 0 to 65,000 if unsigned.

A long int is 32 bits long and can hold very much larger numbers. Can't hold negative numbers if unsigned.

In your formula

test=a*b*60*8/10/c;

all the operators (/ and *) are equal precidence, so should be evaluated in strict left-to-right order.

If the calculation starts with an int, it will stay as an int until it meets a long int. At that point, the rest of the calculation gets done as long int. But if, while the calculation is done as int, it exceeds the limits of int, the calculation will go wrong.

Great!! Thanks for that answer!