Как остановить OverflowException при целочисленном делении? - PullRequest
2 голосов
/ 19 августа 2009

Я получаю OverflowException выдается на меня, когда я не хочу их (или я так думаю). Я выполняю некоторые странные вычисления, где ожидаю переполнения значений, отбрасывая переполненные биты. Кажется, я не могу заставить это работать должным образом все же. По сути, это одна пара i и j, которая происходит, когда я перебираю огромные множества (от int.MinValue до int.MaxValue).

// i and j are ints
// i is -2147483648
// j is -1
var x = i / j;

// I also tried using unchecked keyword, but it doesn't help    
var x = unchecked(i / j);

Обновление:

Ожидаемое математическое значение -2147483648 / -1 равно 2147483648. Однако этот определенный код на самом деле не пытается найти число. Это часть серии манипуляций, которые трудно понять. Честно говоря, я даже сам не знаю, каково было намерение, потому что я на самом деле не документировал метод, и все, что ему понадобилось, - это один день, чтобы поднять серьезные WTF-пузыри над головой. Все, что я знаю, это работает так, как задумано, с помощью специального кода, предназначенного для обработки случая.

Об ожидаемом значении:

Поскольку int может содержать только максимум 2147483647, я ожидаю сбросить выходное значение переполнения 0.

Если я вообще что-то узнал об этом, то, вероятно, важна документация для непонятных методов.

Ответы [ 4 ]

6 голосов
/ 19 августа 2009

Я полагаю, что это случай only , в котором вы получите это исключение. Это единственное деление в диапазоне Int32, которое может переполниться. (Конечно, есть деление на ноль, но это другое исключение.)

Так что, если вы хотите избежать OverflowException, вам только нужно разобраться с этим делом. Что вы хотите от этого? Напишите метод, который определяет этот точный случай, а в противном случае выполняет нормальное деление.

Примечание: это также то, почему вы не должны пытаться отменить сравнение, просто отрицая результат. Если вы хотите отсортировать что-либо в порядке убывания, а не в порядке возрастания, вместо использования -Compare(x, y) используйте Compare(y, x). Отрицание не не дает переполнения для int.MinValue (если вы не в проверенном контексте) - оно просто тихо возвращает int.MinValue.

3 голосов
/ 19 августа 2009

Двойное дополнение означает, что целые числа будут в диапазоне от 2 ^ 32 - 1 до -2 ^ 32, поэтому -2147483648 / -1 возвращает число, которое не может быть представлено int.

Вы можете попробовать поместить его в long. Нет смысла использовать var в этой ситуации.

0 голосов
/ 19 августа 2009

Вы делаете это. Почему вы используете var здесь? Он теряет способность показывать вам тип арифметического результата для сохранения 1 символа ...

long x = (long)i / j;

Если вы хотите насыщения, вы можете:

int x = (int)Math.Min((long)i / j, int.MaxValue);
0 голосов
/ 19 августа 2009

Вы можете обойти это с небольшим приведением к / от Int64:

var x = (int)((long)i / j);
...