C найти максимальное целое число дополнения два - PullRequest
0 голосов
/ 17 октября 2018

Мне поручено найти максимум двух дополнительных чисел, или TMax.Я в полной растерянности, как это сделать.Я знаю, что правильным значением является 0x7fffffff или 2147483647, но я не знаю, как именно получить этот результат.Это максимальное число для 32-битного целого числа.Я не могу использовать функции или условия, и самое большее, я могу использовать 4 операции.Может кто-нибудь попытаться помочь мне объяснить это?Я знаю способ найти максимальное число для определенного количества битов: 2 ^ (биты - 1) - 1, поэтому 2 ^ (31) - 1 = 2147483647

Ответы [ 4 ]

0 голосов
/ 18 октября 2018

Спасибо всем за помощь!Оказывается, я не могу использовать макросы, unsigned или long.Я пришел к этому решению:

~(1 << 31)

Это генерирует правильный вывод, поэтому я оставлю это на этом!

0 голосов
/ 17 октября 2018

найти максимальное целое число дополнения до двух

int TMax = -1u >> 1 или -1u/2 достаточно, когда INT_MAX == UINT_MAX/2 достаточно, чтобы найти максимум int,

Это "работает«даже если int закодировано как дополнение 2 или теперь редкое дополнение 1 или величина знака.


Лучше использовать

#include <limits.h>
int TMax = INT_MAX;

Другие приемы могут включать неопределенное, определяемое реализацией, неопределенное поведение , которого лучше избегать в C.

0 голосов
/ 18 октября 2018

Существует два сценария, в которых вы можете искать максимальное положительное число, либо с заданным целочисленным типом данных, либо с заданным количеством битов.Также есть два решения:

Заполнение и сдвиг вправо

Работа с целочисленным типом данных с размером, точно совпадающим с размером желаемого типа данных, дополняющего двойку,Вы можете решить проблему с помощью

(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 бита или больше, в зависимости от вашей платформы.

0 голосов
/ 17 октября 2018

Предполагая, что вы знаете, что ваша машина использует представление дополнения до двух, вы будете делать это стандартным образом:

unsigned int x = ~0u;
x >>= 1;
printf("max int = %d\n", (int)x);

Используя unsigned int, вы предотвращаете любое поведение, определяемое реализацией, вызванноесдвигая вправо отрицательное значение.

...