C ++ долго переполняется преждевременно - PullRequest
7 голосов
/ 22 февраля 2010

У меня странная проблема с C ++, когда длинный тип данных переполняется задолго до того, как должен. Что я делаю (пока с успехом), так это чтобы целые числа вели себя как числа с плавающей точкой, чтобы диапазон [-32767,32767] отображался в [-1.0,1.0] Где он спотыкается, с большими аргументами, представляющими числа с плавающей запятой, больше чем 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));
}

Что я получаю в качестве вывода:

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

То есть время (98301,32767) аналогично 3,0 * 1,0. Этот код прекрасно работает, когда аргументы для времен меньше 32767 (1.0), но ни один из промежуточных шагов с приведенными выше аргументами не должен превышать 64 бита.

Есть идеи?

Ответы [ 4 ]

9 голосов
/ 22 февраля 2010
Длина

не обязательно 64 бита. вместо этого попробуйте «длинный длинный».

4 голосов
/ 22 февраля 2010

Тип long не обязательно является 64-битным. Если вы используете 32-битную архитектуру (по крайней мере, в MS Visual c ++), тип long составляет 32 бита. Проверьте это с sizeof (long). Также может помочь тип данных long long.

2 голосов
/ 22 февраля 2010

Стандарт C гарантирует только то, что long будет иметь по крайней мере 32-битную версию (что на самом деле имеет место на большинстве 32-битных платформ).

Если вам нужно 64 бит, используйте long long. Он гарантированно удерживает как минимум 64 бита.

2 голосов
/ 22 февраля 2010

У вас, вероятно, есть 32-битные длинные. Попробуйте использовать long long вместо.

98301 * 32767 = 3221028867, а 32-разрядное длинное переполняется при 2147483648

...