Абсолютное значение INT MIN [дубликат]
На этот вопрос уже есть ответ здесь:
- правильный способ взять абсолютное значение INT_MIN 4 ответа
- Почему абсолютное значение максимального отрицательного целого числа -2147483648 все еще равно -2147483648? 5 ответов
Как я мог извлечь абсолютное значение INT_MIN
без переполнения? Смотрите этот код для решения проблемы:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("INT_MAX: %dn", INT_MAX);
printf("INT_MIN: %dn", INT_MIN);
printf("abs(INT_MIN): %dn", abs(INT_MIN));
return 0;
}
Выплевывает следующее
INT_MAX: 2147483647
INT_MIN: -2147483648
abs(INT_MIN): -2147483648
Мне это нужно для проверки, если значение int
больше нуля.
Что касается этого вопроса, являющегося дубликатом , почему абсолютное значение максимального отрицательного целого числа -2147483648 все еще равно -2147483648?Я вынужден не согласиться, поскольку это вопрос "как", а не "почему".
6 ответов:
Спецификатор преобразования
%d
в строке форматаprintf
преобразует соответствующий аргумент в знаковое десятичное целое число, которое в этом случае переполняется для типаint
. Стандарт C специально упоминает, что переполнение целого числа со знаком является неопределенным поведением. То, что вы должны сделать, это использовать%u
в строке формата. Также необходимо включить заголовкиstdio.h
иstdlib.h
для прототипа функцийprintf
иabs
соответственно.#include <limits.h> #include <stdio.h> #include <stdlib.h> // This solves the issue of using the standard abs() function unsigned int absu(int value) { return (value < 0) ? -((unsigned int)value) : (unsigned int)value; } int main(void) { printf("INT_MAX: %d\n", INT_MAX); printf("INT_MIN: %d\n", INT_MIN); printf("absu(INT_MIN): %u\n", absu(INT_MIN)); return 0; }
Это дает выход на мой 32-разрядная машина:
INT_MAX: 2147483647 INT_MIN: -2147483648 absu(INT_MIN): 2147483648
Как насчет
printf ("abs(INT_MIN) = %ld", -((long int) INT_MIN));
Или если ваш
long
не длиннееint
:printf ("abs(INT_MIN) = %lld", -((long long int) INT_MIN));
Или если вы готовы принять, что
abs(INT_MIN)
ВсегдаINT_MAX + 1
:printf ("abs(INT_MIN) = %u", ((unsigned int) INT_MAX ) + 1 );
Нет переносимого способа извлечь абсолютное значение самого отрицательного числа в виде целого числа. Стандарт ISO C гласит:(§6.2.6.2¶2):
Каждый бит, являющийся битом значения, должен иметь то же значение, что и тот же бит в объекте. представление соответствующего беззнакового типа (если в знаке имеется M бит значений тип и Н-тип unsigned, то m ≤ П ).Обратите внимание, что он использует ≤, а не <.>
Так как знаковый бит в дополнении 2 имеет значение -(2М), и значение каждого бита имеет определенное значение, которое является степенью двух между 1 и 2м-1, нет возможности беззнаковое целое, на реализации, где м=н может представлять 2Н, он может только представлять до 2Н-1 = 1+2+...+2 N-1.
В C существует только версия int для функции
int abs(int j)
. Вы можете использовать другую функциюlabs
под заголовкомstdlib.h
. Его прототип:long int labs(long int j);
#include <limits.h> #include <stdio.h> #include <stdlib.h> int main(void) { printf("INT_MAX: %d\n", INT_MAX); printf("INT_MIN: %d\n", INT_MIN); printf("abs(INT_MIN): %ld\n", labs((long)INT_MIN)); return 0; }
Приведение к следующему доступному большему целочисленному типу должно сделать это. но вы должны использовать соответствующий АБС-вариант (в данном случае
llabs(...)
)printf("llabs(INT_MIN): %lld\n", llabs((long long int)INT_MIN));
Редактировать:
Вы можете проверить, что является следующим большим типом, сравнивая
INT_MIN
сLONG_MIN
иLLONG_MIN
. Может быть, в вашем случае приведение кlong
уже сделает это.Обратите внимание, что явные приведения на самом деле не нужны, так как сама функция будет приводить аргумент неявноprintf("labs(INT_MIN): %ld\n", labs((long int)INT_MIN));
Во-первых, вы должны
Во-вторых, если единственное, чего вы хотите достичь, - это вывести абсолютное значение#include <math.h>
правильно использовать функциюabs
.INT_MIN
, определенное вlimits.h
, Вы можете просто распечатать его какunsigned integer
или какlong long integer
, например:printf( "abs(INT_MIN): %u\n", abs( INT_MIN ) ); // %u for unsigned int printf( "abs(INT_MIN): %lld\n", abs( INT_MIN ) ); // %lld for long long int
Поскольку вы хотите иметь абсолютное значение, которое наверняка будет без знака, это должно быть нормально.
Если вы не хотите включать
math.h
, вы можете сделать это самостоятельно, как это:// ternary implementation of the function abs printf( "abs(INT_MIN): %u\n", ( INT_MIN > 0 ) ? INT_MIN : -INT_MIN );
Если вы хотите использовать его для других целей, то вы можете хранить значение
abs( INT_MIN )
в переменныхunsigned int
илиlong long int
.