Проблемы с проверкой целого числа ноль или отрицательный только с оператором в C? - PullRequest
0 голосов
/ 05 декабря 2018
     /*
     * 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.
     *   Legal ops: ! ~ & ^ | + << >>
     *   Max ops: 20
     *   Rating: 4
     */
    int isPower2(int x) {
      /*
   * Variable a checks if x is power of 2, x and x - 1 won't have a 1
   * in the same place if it's power of 2. Variable b checks if x is
   * negative or zero. Use & to combine !a and b to complete the function.
   */
        int a = x &(x+(~1+1));
        int b = ((x+(~1+1))>> 31)+1;
        return (!a)&b;

    }

Привет всем, я самостоятельно изучаю курс под названием CSE351 из Университета Вашингтон и заканчиваю лабораторию 1 по манипулированию данными в C. Как вы можете видеть по этому вопросу, мне нужно использовать переменную b, чтобы сказатьдействительно ли int x равен нулю.

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

Но, однако, мой код не работал, но я обнаружил, что строка кода работает.

  int b = ((!(x >> 31)) & (~(!x)));

Я действительно запутался, почему мой код не работает, может кто-нибудь сказать мнепочему?

Редактировать: Извините, я не упомянул, что среда этой лаборатории основана на 32-разрядном int и дополнении 2 для отрицательного.

1 Ответ

0 голосов
/ 10 декабря 2018

Обратите внимание на несколько вещей (в вашем коде):

  • 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));
    }
}
...