Pages: [1]   Go Down
Author Topic: Can someone explain this? [solved]  (Read 1057 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have, what I thought was a pretty straightforward multiplication operation, but....

Code:
uint32_t p =0;

void setup(){
  Serial.begin(9600);
  p = 15*60*1000;
  Serial.print("Trial 1: "); Serial.println(p);
  p = 15*60;
  p = p*1000;
  Serial.print("Trial 2: "); Serial.println(p);
  p = 15*60;
  p *= 1000;
  Serial.print("Trial 3: "); Serial.println(p);
}

void loop(){
}

Yields:
Trial 1: 4294949792
Trial 2: 900000
Trial 3: 900000

What the f@!#^*?

I can't figure out why Trial 1 give such a wacky number. I thought it was wrap around or maybe the way print works, but as you can see the other trials work just fine. So what is going on? And here I thought I understood this stuff...

-- Thanks!
« Last Edit: October 14, 2012, 12:16:59 am by Nick Gammon » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 547
Posts: 45935
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Literals, like 15, 60, and 1000, are interpreted as ints, in the absence of any directive to the contrary. Nothing in the first calculation is larger than an int, so ints are used in the calculation. The result overflows an int. That the result is stored in a long is irrelevant.

In the second case, 15 * 60 is an int, stored in a long. Then the long is multiplied by an int, which is promoted to a long. The result is a long, which is stored in a long.

The third case is identical to the second. p = p * 1000 is identical to p *= 1000.
Logged

Offline Offline
Edison Member
*
Karma: 31
Posts: 1417
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

15*60 = 900 which fits into a 16-bit integer.
900*1000 = 900000 which doesn't fit. The result is truncated to 16-bit and sign-extended.
900000 = DBBA0 (hex). Truncate to 16 bits = BBA0. This is negative so sign-extend it to 32 bits FFFFBBA0. This value is then stored in p. Converting this as an unsigned 32-bit integer to decimal gives 4294949792.

Pete
Logged

Where are the Nick Gammons of yesteryear?

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ahhh, that makes a lot of sense.  I knew it had to do something with the size of the variable, just couldn't see how.
Thanks a lot for the help!
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So could I do something like this:

p = 15L*60L*1000L to force the operation to use longs for the calculation.

Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 547
Posts: 45935
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So could I do something like this:

p = 15L*60L*1000L to force the operation to use longs for the calculation.
Yes, you could. And should.

L = long
UL = unsigned long
Logged

Pages: [1]   Go Up
Jump to: