Существует два сценария, в которых вы можете искать максимальное положительное число, либо с заданным целочисленным типом данных, либо с заданным количеством битов.Также есть два решения:
Заполнение и сдвиг вправо
Работа с целочисленным типом данных с размером, точно совпадающим с размером желаемого типа данных, дополняющего двойку,Вы можете решить проблему с помощью
(unsigned 'type') ^0)>>1
или, что эквивалентно,
(unsigned 'type') ^0)/2.
Например, на машине с коротким 16 битами,
(unsigned short) ^0 ==> 0xFFFF (65535)
((unsigned short) ^0 ) >> 1 ==> 0x7FFF (32767)
Для 32-битного типа данных этот метод дает нам 0x7FFFFFFF (2147483647).
В C целочисленный тип имеет только минимальный размер, например, int может быть 16 бит, 32бит или больше.Но размер слова, используемый в расчете, должен точно соответствовать предполагаемому целевому значению.
Также обратите внимание, что данные должны быть беззнакового типа.Сдвиг вправо для типа со знаком обычно реализуется как сдвиг знака со знаком (бит знака копируется в результат).
Установить только бит знака и вычесть 1
Второй метод, который работает для любого размера слова, равного или большего, чем число битов желаемого размера слова, дополняющего двойки, составляет
(unsigned integer_type) 1<<(n-1)-1
Например, для любого целочисленного размера слова больше илибольше 16, мы можем найти TMAX для 16 как
(unsigned integer_type) 1<<15 ==> binary 1000 0000 0000 0000 (0x8000)
(unsigned integer_type) (1<<15 - 1) == > 0111 1111 1111 1111 (0x7FFF)
. Это надежно и работает практически в любом сценарии, который обеспечивает адекватный размер слова.
Опять тип данных для расчета имеетбыть без знака, если размер слова в расчете соответствует размеру слова цели.Это не обязательно для большего размера слова.
Примеры
В первом примере мы покажем, что второй метод работает для 32 бит, используя long или long longтипов.
#include <stdio.h>
int main() {
printf( "%ld\n", (long) ( ( ((unsigned long) 1)<<31 ) - 1 ) );
printf( "%lld\n", (long long) ( ( ((unsigned long long) 1)<<31 ) - 1 ) );
}
Вывод:
2147483647
2147483647
И здесь мы показываем, что первый метод, сдвиг вправо от всех установленных битов, завершается неудачно, когда int не совсем 32 бита, что, как отмечено, не гарантируется в C.
#include <stdio.h>
int main() {
printf( "from long long %lld (%zu bits)\n", ( (unsigned long long) ~0 )>>1,
sizeof(unsigned long long)*8 );
printf( "from long %ld (%zu bits)\n", ( (unsigned long) ~0 )>>1,
sizeof(unsigned long)*8 );
printf( "from int %d (%zu bits)\n", ( (unsigned int) ~0 )>>1,
sizeof(unsigned int)*8 );
printf( "from short %d (%zu bits)\n", ( (unsigned short) ~0 )>>1,
sizeof(unsigned short)*8 );
}
Вывод:
from long long 9223372036854775807 (64 bits)
from long 9223372036854775807 (64 bits)
from int 2147483647 (32 bits)
from short 32767 (16 bits)
Опять же, напомним, что язык C гарантирует только минимальный размер для любых целочисленных типов данных. int может быть 16 бит или 32 бита или больше, в зависимости от вашей платформы.