Подтвердить что ты не робот

Почему абсолютное значение максимального отрицательного целого числа -2147483648 равно -2147483648?

Результат абс (-2147483648) равен -2147483648, не так ли? это кажется неприемлемым.

printf("abs(-2147483648): %d\n", abs(-2147483648));

выход:

abs(-2147483648): -2147483648
4b9b3361

Ответ 1

В стандарте говорится о abs():

Функции abs, labs и llabs вычисляют абсолютное значение целого числа j. Если результат не может быть представлен, поведение undefined.

И результат действительно не может быть представлен, поскольку представление с двумя дополнениями целых чисел со знаком не является симметричным. Подумайте об этом... Если у вас есть 32 бита в int, это дает вам 2 32 различные значения от INT_MIN до INT_MAX. Это четное число значений. Итак, если есть только один 0, число значений больше 0 не может быть таким же, как число значений меньше 0. И поэтому нет никакого положительного аналога INT_MIN со значением - INT_MIN.

Итак, что неприемлемо вызывает abs(INT_MIN) на вашей платформе.

Ответ 2

Так как 2147483648 больше, чем INT_MAX для вашей реализации, то abs(-2147483648) - undefined.

Ответ 3

Отрицательные числа обычно представляются без двоичного дополнения.

Чтобы преобразовать положительный в отрицательный, используется логика

x -> not(x)+1

Для 8-битовой арифметики

01111111b - 127, а -127 - 10000000b + 1 = 10000001b

и в противоположном направлении -127 10000001b станет
01111110b + 1 = 01111111b

Как насчет -128?

-128 равен 10000000b, и нет никакого положительного его аналога, поскольку нет 128-битной арифметики, подписанной в 8 бит.

10000000 → 01111111 + 1 = 10000000 и -128 снова

То же самое относится к оригинальному вопросу

Ответ 4

Это код в abs.c в исходном коде GNU glibc.

/* Return the absolute value of I.  */
int
DEFUN(abs, (i), int i)
{
  return(i < 0 ? -i : i);
}

Итак, abs (-2147483648) return - (- 2147483648). В x86 он реализуется с помощью этой двух команд

movl    $-2147483648, %eax
negl    %eax

Negl-инструкция реализуется следующим образом: Num = 0-Num; sbb реализуется следующим образом: Вычитает источник из адресата и вычитает 1 дополнительный, если установлен флаг переноса. Таким образом, abs (-2147483648) (hex - 0x80000000) → - (- 2147483648) → 0 - (- 2147483648), наконец, становится (0x80000000).

подробности инструкции negl, пожалуйста посетите http://zsmith.co/intel_n.html#neg

подробности инструкции sbb, пожалуйста, посетите http://web.itu.edu.tr/kesgin/mul06/intel/instr/sbb.html

Ответ 5

Попробуйте это

printf("abs(-2147483648): %u\n", abs(-2147483648));