Проверьте, не переполнится ли сумма двух целых - PullRequest
7 голосов
/ 07 августа 2011

Из ловушек и ловушек C

Если a и b - две целочисленные переменные, которые, как известно, неотрицательны, то для проверки, может ли a+b переполнение, использовать:

     if ((int) ((unsigned) a + (unsigned) b) < 0 )
        complain();

Я не понял, как сравнение суммы обоих целых чисел с нулем даст вам понять, что существует переполнение?

Ответы [ 7 ]

17 голосов
/ 07 августа 2011

Код, который вы видели для тестирования на переполнение, является просто фальшивым.

Для целых чисел со знаком вы должны тестировать так:

if (a^b < 0) overflow=0; /* opposite signs can't overflow */
else if (a>0) overflow=(b>INT_MAX-a);
else overflow=(b<INT_MIN-a);

Обратите внимание, что случаи могут быть значительно упрощены, еслиодно из двух чисел является константой.

Для целых чисел без знака вы можете проверить это следующим образом:

overflow = (a+b<a);

Это возможно, поскольку арифметика без знака определена для переноса, в отличие от арифметики со знаком, которая вызываетнеопределенное поведение при переполнении.

2 голосов
/ 24 июля 2013

Если известно, что a и b являются неотрицательными целыми числами, последовательность (int) ((без знака) a + (без знака) b) действительно вернет отрицательное число при переполнении.

Предположим, что 4-битная (макс. Положительное целое число равно 7, а макс. Целое число без знака равно 15) система со следующими значениями:

a = 6

b = 4

a + b = 10 (overflow if performed with integers)

Если мы сделаем дополнение, используя беззнаковое преобразование, у нас будет:

int((unsigned)a + (unsigned)b) = (int) ((unsigned)(10)) = -6

Чтобы понять почему, мы можем быстро проверить двоичное дополнение:

a = 0110 ; b = 0100 - first bit is the sign bit for signed int.

0110 +
0100
------
1010

For unsigned int, 1010 = 10. При том же представлении in signed int means -6.

Таким образом, result операции действительно < 0.

2 голосов
/ 07 августа 2011

Когда происходит переполнение, сумма превышает некоторый диапазон (скажем так):

-4,294,967,295 < sum < 4,294,967,295

Поэтому, когда сумма переполняется, она оборачивается и возвращается к началу:

4,294,967,295 + 1 = -4,294,967,295

Если сумма отрицательна и вы знаете , эти два числа положительны, то сумма переполнена.

1 голос
/ 02 февраля 2013

Если целые числа без знака и вы предполагаете IA32, вы можете выполнить некоторую встроенную сборку, чтобы проверить значение флага CF.Я знаю, что асм можно немного обрезать.

int of(unsigned int a, unsigned int b)
{
        unsigned int c;

        __asm__("addl %1,%2\n"
                "pushfl \n"
                "popl %%edx\n"
                "movl %%edx,%0\n"
                :"=r"(c)
                :"r"(a), "r"(b));

        return(c&1);
}
0 голосов
/ 12 июня 2015

при допущении представления двойного дополнения и 8-битных целых чисел старший значащий бит имеет знак (1 для отрицательного и 0 для положительного), поскольку мы знаем, что целые числа неотрицательны, это означает, что старший значащий бит равен 0 для обоих целых чисел.Теперь, если добавление беззнакового представления этих чисел приводит к значению 1 в старшем значащем бите, то это означает, что при добавлении переполнено, и для проверки, имеет ли целое число без знака 1 в старшем значащем бите, нужно проверить, больше ли оно диапазонацелое число со знаком, или вы можете преобразовать его в целое число со знаком, которое будет отрицательным (поскольку старший значащий бит равен 1)

например, 8-битные целые числа со знаком (диапазон от -128 до 127):

twos compliment of 127 = 0111 1111
twos complement of 1   = 0000 0001

unsigned 127           = 0111 1111
unsigned 1             = 0000 0001
unsigned sum           = 1000 0000

сумма равна 128, что не является переполнением для целого числа без знака, но является переполнением для целого числа со знаком, старший бит его отдает.

0 голосов
/ 28 мая 2014

Как мы знаем, добавление 2 чисел может быть переполнением.Для этого мы можем использовать следующий способ сложения двух чисел.

Концепция сумматора

Предположим, у нас есть 2 числа "a" И "b"

(a ^ b) + (а & б);это уравнение даст правильный результат .. И это запатентовано Samsung.

0 голосов
/ 07 августа 2011

Есть несколько хороших объяснений на этой странице .

Вот простой способ из той страницы, которая мне нравится:

Do the addition normally, then check the result (e.g. if (a+23<23) overflow).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...