Абсолютное значение 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.