Потратьте 3 часа на эту проблему. Я знаю, что эта проблема исходит из лаборатории данных csapp, и ее новейшее требование -
1. Integer constants 0 through 255 (0xFF), inclusive. You are
not allowed to use big constants such as 0xffffffff
....
* isTmax - returns 1 if x is the maximum, two's complement number,
* and 0 otherwise
* Legal ops: ! ~ & ^ | +
* Max ops: 10
* Rating: 1
Итак, оператор сдвига (<<
/ >>
и 0x7FFFFFFF
из принятого ответа теперь запрещен)
Ниже мой путь:
TDD-стиль:
isTmax(2147483647) == isTmax(0b011111111111...1) == 1
isTmax(2147483646) == isTmax(0b011111111111...0) == 0
isTmax(-1) == isTmax(0b111111111...1) == 0
isTmax(-2147483648) == isTmax(0b100000000...0) == 0
возврат должен быть либо 0
, либо 1
. In, c, !
+ все ненулевые значения вернут 0
. Так что !
является обязательным, в противном случае мы не можем гарантировать получение 0
для всех номеров.
Первая наивная попытка:
потому что 0b0111111...1
(он же 2147483647
) является единственным аргументом, который должен сделать isTmax
return 1
, а 2147483647 + 1
должно быть 10000000...0
(он же -2147483648
)
0b011111111...1 xor 0b1000000000...0
- это 0b11111111111...111
. Поскольку мы должны использовать !
, мы надеемся увидеть 0
(он же 0b0000000000000...0
). Очевидно, просто примените логика, а не (он же !
) к 0b1111111...1
), тогда мы получим 0b000000000000
):
!(~(x ^ (x + 1))
давайте распечатаем это
void print(int x)
{
printf("%d\n", !(~(x ^ (x + 1))));
}
int main() {
print (2147483647);
print(2147483646);
print(-1);
print(-2147483648);
}
* * 1 тысяча сорок-девять
0
1
0
live demo
Неплохо, только -1
работает не так, как мы ожидали.
вторая попытка:
Давайте сравним -1
и 2147483647
11111111111111111111111111111111
01111111111111111111111111111111
Мы можем найти -1 + 1 = 0
, а 2147483647 + 1 = -2147483648
. Еще раз подчеркнем, что нам нужны diff -1
и 2147483647
, потому что они оба возвращают 1
, как показано выше. Посмотрите назад на защиту логики , а не в c: все ненулевые вернут 0 , поэтому !-2147483648 == 0
и !(-1 + 1) != 0
. Просто измените левую часть x ^ (x + 1)
(x
) на x + !(x + 1)
. Если х равен 2147483647
, x + !(x + 1)
будет равен x
.
Запустить снова:
void print(int x)
{
printf("%d\n", !(~( x + !(x + 1) ^ (x + 1))));
}
int main() {
print (2147483647);
print(2147483646);
print(-1);
print(-2147483648);
}
1
0
0
0
live demo
Готово!