When math fails.

In the Arduino IDE; this fails:

unsigned long  CheckTime = (5*1000*60); // CheckTime has WRONG value

but this works:

unsigned long  CheckTime = (5*1000); Checktime *= 60;

Why does the 1st fail? it is legal C code...

You need to cast the constants as long by default they are ints.

unsigned long  CheckTime = (5ul*1000ul*60ul);

I have a post about that:

http://www.gammon.com.au/forum/?id=12146

Why does the 1st fail? it is legal C code...

Yes and it is doing what the C standard requires it to do.

Grumpy_Mike: You need to cast the constants as long by default they are ints.

While on the surface that answer seems good; but it isn't -- w/o casting; it works fine if done in two steps instead of 1. No casting, so shouldn't there still be an error?

jAssing:

Grumpy_Mike: You need to cast the constants as long by default they are ints.

While on the surface that answer seems good; but it isn't -- w/o casting; it works fine if done in two steps instead of 1. No casting, so shouldn't there still be an error?

5*1000 fits in an int, 5*1000*60 does not.

jAssing: While on the surface that answer seems good; but it isn't -- w/o casting; it works fine if done in two steps instead of 1. No casting, so shouldn't there still be an error?

All of 5, 1000 and 60 fit into an int. So there is no problem with the raw numbers. Plus the compiler will promote a number like 100000 into an appropriate size.

However making the first one a long makes the calculation be done as a long.

BTW that isn't casting. Casting looks like this:

unsigned long  CheckTime = (long ) 5 * (long) 1000 * (long) 60;

jAssing:

Grumpy_Mike:
You need to cast the constants as long by default they are ints.

While on the surface that answer seems good; but it isn’t – w/o casting; it works fine if done in two steps instead of 1. No casting, so shouldn’t there still be an error?

If you do the calculation in one step:

unsigned long  CheckTime = 5*1000*60 ;

5 * 1000 yields 5000 which fits in an int and both sides of the multiply are already int,
the result is 16 bit. Then we do the 5000 * 60, again both sides are 16 bit, so a 16 bit multiply
is used and it overflows given an erroneous result.
Lastly we do the assignement, and only now does the value get widened to 32 bit, too late.

Now two steps:

unsigned long  CheckTime = 5*1000 ;
CheckTime *= 60 ;

So now the 5000 result is widened and stored in CheckTime as 32 bit and correct.
The second multiply is between a 32 bit variable and a 16 bit constant (60). The rules
in C mean that before the multiply both sides are brought up to the widest type,
32 bits, and then a 32 bit multiply is done.

Basically in C the type of an expression depends only on the type of both sides (the
subexpressions) and not the LHS of the assignment.

Whenever you write 10 you create a constant of type int, and for the Arduino int
is 16 bits.

w/o casting; it works fine if done in two steps instead of 1.

When you used two steps, there was an implicit cast to long that happened when you assigned the first int result to a long variable.

westfw: [When you used two steps, there was an implicit cast to long that happened when you assigned the first int result to a long variable.

AH, yes! That's what I wasn't seeing. Thanks.