Обратите внимание на несколько вещей (в вашем коде):
- first,
(~1 + 1)
- это то же самое, что и ~0
, и то же самое, что и -1
(в дополнении к двум).Проще, верно? x + (~0)
- это то же самое, что и x - 1
.Проще, верно? x & (x - 1)
- это 1
все биты, которые не изменяют и равны 1 , когда x
уменьшается.Я думаю, что вы притворяетесь, что пишете x ^ (x - 1)
, то есть набор битов, которые переходят к следующему на декременте.Это биты, которые меняются в порядке уменьшения.Бывает, что все биты меняются, если число является степенью двойки.Если вам нужны биты, которые не меняются, вместо использования ^
, просто используйте &
(биты, которые равны 1
и не меняются при уменьшении , которое должно быть пустымустановить в случае степени два --- мы должны дополнить результат, так как это логическое значение дает противоположное значение) Это выражение может быть результатом для получения степени два, если вы рассмотрите особый случай 0
, которыйвернулся как сила двух.Как и с отрицательными значениями и 0, логарифм не существует, поэтому мы можем просто сказать if (x <= 0) return 0; else return !(x & (x - 1));
(ЭТО МОЖЕТ БЫТЬ ЗАПРОШЕННОЕ РЕШЕНИЕ) или более компактный return x <= 0 ? 0 : !(x&(x-1));
. ~a
как следствие _allбиты, которые изменяют ИЛИ, равны 0 , когда x
уменьшается.Я полностью потерялся в том, что ты притворяешься.Я думаю, что вы хотите получить, если x <= 0
, но это так легко написать на C, вместо того, чтобы показывать сложности, которые вы показываете.
Итак, ваши намерения (я предполагаю) - использовать число 1биты, которые не меняются при уменьшении, поскольку все биты меняются для степеней двойки. Тогда возможная реализация должна быть:
#include <stdio.h>
/*
* isPower2 - returns 1 if x is a power of 2, and 0 otherwise
* Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0
* Note that no negative number is a power of 2. (and zero also, there's no logarithm of zero)
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 4
*/
int isPower2(int x) {
return x <= 0
? 0
: !(x&(x-1));
}
/* please, always post complete and verifiable code, with header files,
* and the like, so we can test it without having to first modify it.
*/
int main()
{
for (;;) {
int a;
scanf("%d", &a);
printf("isPower2(a=%d) => %d\n", a, isPower2(a));
}
}
NOTE
В любом случае, у меня нет четкого представления о результате, который вы хотите получить, так как вы задаете вопрос как Проблемы с проверкой целого числа - ноль или отрицание ... и затем вы показываете частичный код (см. Как создать минимальный, полный и проверяемый пример ) о как определить, является ли некоторое данное целое число степенью двух , но затем вы показываете какой-то странный код, чтобы проверить, есличисло отрицательное.Достаточно сделать:
if (x <= 0) do_bla_bla();
, и это не приведет к неопределенному поведению с 31-битным сдвигом вправо.
NOTE
, если вам нужно использовать только операторы всписок, просто измените <=
на следующее:
#define SIGNBIT (~(~0>>1)) /* ALL ONES, SHIFTED ONE BIT RIGHT AND COMPLEMENTED */
return
x & SIGNBIT /* sign bit on, negative number */
|| !x /* OR x == 0 */
? 0
: !(x&(x-1));
Окончательный код:
#include <stdio.h>
/*
* isPower2 - returns 1 if x is a power of 2, and 0 otherwise
* Examples: isPower2(5) = 0, isPower2(8) = 1, isPower2(0) = 0
* Note that no negative number is a power of 2. (and zero also, there's no logarithm of zero)
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 4
*/
#define SIGNBIT (~(~0>>1))
int isPower2(int x) {
return x & SIGNBIT || !x ? 0 : !(x&(x-1));
/* if anybody tells you are using ? and || operators, just write:
* if (x & SIGNBIT) return 0;
* if (!x) return 0;
* return !(x&(x-1));
*/
}
/* please, always post complete and verifiable code, with header files,
* and the like, so we can test it without having to first modify it.
*/
int main()
{
for (;;) {
int a;
scanf("%d", &a);
printf("isPower2(a=%d) => %d\n", a, isPower2(a));
}
}