views:

118

answers:

4

Hello there,

I'm having a bizarre problem with C++ where the long data type is overflowing long before it should. What I'm doing (with success so far) is to have integers behave like floats, so that the range [-32767,32767] is mapped to [-1.0,1.0]. Where it stumbles is with larger arguments representing floats greater than 1.0:

inline long times(long a, long b) {
  printf("a=%ld b=%ld ",a,b);
  a *= b;
  printf("a*b=%ld ",a);
  a /= 32767l;
  printf("a*b/32767=%ld\n",a);
  return a;
}

int main(void) {
  printf("%ld\n",times(98301l,32767l));
}

What I get as output is:

a=98301 b=32767 a*b=-1073938429 a*b/32767=-32775
-32775

So times(98301,32767) is analogous to 3.0*1.0. This code works perfectly when the arguments to times are less than 32767 (1.0), but none of the intermediate steps with the arguments above should overflow the 64 bits of long.

Any ideas?

+7  A: 

long is not necessarily 64 bits. try 'long long' instead.

gbrandt
It works! Thanks to everyone who suggested this, what a drag. Makes me appreciate Java so much more...
rhodri
@rhodri: long long isn't even necessarily 64-bits, by the way (on certain implementations). Check out Boost Integer or see if your compiler has stdint.h.
GMan
@GMan: Correct. However, the C standard guarantees that `long long` has *enough range* for a 64bit integer, and that is usually enough...
sleske
+1  A: 

You probably have 32-bit longs. Try using long long instead.

98301 * 32767 = 3221028867, while a 32-bit long overflows at 2147483648

Gabe
+2  A: 

The type long is not necessarily 64 bits. If you are on the 32 bit architecture (at least on MS Visual c++), the long type is 32 bits. Check it out with sizeof (long). There is also the long long data type that may help.

Kerido
+1  A: 

The C standard only guarantees that long will have at least 32 bit (which is actually the case on most 32bit platforms).

If you need 64 bit, use long long. It's guaranteed to hold at least 64 bit.

sleske