Проверять положительные или отрицательные значения без использования условных операторов в java

Вопрос интервью, который я задал на прошлой неделе:

Мне нужна функция, чтобы распечатать, является ли число положительным или отрицательным, не используя условные выражения типа if else while for switch a? b:c и т.д. Как я могу это сделать.

Я сказал интервьюеру, что это невозможно, потому что вопрос носит "условный характер". Он сказал мне, что это возможно, но не сказал мне, как это сделать. Я сделал довольно много поиска, но никаких хороших ответов.

Ответ 1

Одно из возможных решений:

String[] responses = {"Positive", "Negative"};
System.out.println(responses[(i >> 31) & 1]);

Это также считается нулем в качестве положительного числа.

Поскольку целые числа в Java должны храниться в два дополнения (или вести себя так, как если бы они были), самый старший бит любого отрицательного числа 1, а старший бит любого другого числа равен 0. (i >> 31) копирует самый старший бит на каждый другой бит (поэтому отрицательные числа становятся 11111111 11111111 11111111 11111111, а положительные/нулевые числа становятся 00000000 00000000 00000000 00000000). & 1 устанавливает для всех, кроме младшего разряда, значение 0. Комбинация (i >> 31) & 1 эффективно читает только самый старший бит i.

Ответ 2

Вот вариант, учитывающий тот факт, что нуль не является ни положительным, ни отрицательным:

    int x = (int)Math.sqrt(Math.pow(n, 2));
    try {
        x = n / x;
    }
    catch (ArithmeticException e) {
        x = 0;
    }

    String[] result = {"negative", "zero", "positive"};
    System.out.println(result[x + 1]);

Ответ 3

Просто, чтобы подробно остановиться на immibis, ответьте немного:

int index(int i) {
    return 1 + (i>>31) - (-i>>31);
}

String[] text = {"negative", "zero", "positive"};

private String text(int i) {
    return text[index(i)];
}

Подписанный сдвиг i>>31 преобразует каждое отрицательное число в -1 и все остальные в 0. Вычисление -i>>31 позволяет отличать положительные числа от неположительных. Теперь посмотрим на вычисленный index:

positive: 1 +    0 - (-1) = 2
zero:     1 +    0 -    0 = 1
negative: 1 + (-1) -    0 = 0

Ответ 4

Супер простое решение, злоупотребляющее тем, что массивы не могут иметь отрицательный размер:

void printPositive(int i) {
    try { new int[i]; System.out.println("positive"); } 
    catch( NegativeArraySizeException e) { System.out.println("negative"); }
}

Хорошо, этот ответ может выделять огромный массив, если i положителен, и VM может использовать условные обозначения под его капотом при оценке new int[i], но по крайней мере это покажет интервьюеру какое-то творчество. Кроме того, это может показать интервьюеру, что вы можете придумать "из коробки" (потому что он может ожидать, что вы будете делать немного магии, как и большинство других ответов) и сделать что-то совершенно другое.

Ответ 5

Старый ответ. Причина, по которой я делаю этот новый ответ, заключается в том, что я использовал метод Boolean compareTo, который использует тернарный оператор для преобразования булевых выражений в двоичные.

Вот мой новый ответ, который намного нечитабелен.

public static String positiveOrNegative(int n) {

    ArrayList<String> responses = new ArrayList<String>();
    // first element should be "Zero", so if n is 0, the response is "Zero"
    responses.add("Zero");

    // this populates the ArrayList with elements "Positive" for n elements
    // so that if n is positive, n will be an index in the ArrayList
    // and the return will be "Positive"
    // but still if n is negative, it will never be an index in the ArrayList
    for (int i = 0; i < n; i++) {
        responses.add("Positive");
    }

    String response = "";
    try {
        // try to get a response from the ArrayList
        response = responses.get(n);
    } catch (Exception e) {
         // index is out of bounds, so it must have been negative
        response = "Negative";
    }

    return response;
}

public static void main(String[] args) {
    System.out.println(positiveOrNegative(4)); // Positive
    System.out.println(positiveOrNegative(1)); // Positive
    System.out.println(positiveOrNegative(0)); // Zero
    System.out.println(positiveOrNegative(-1)); // Negative
    System.out.println(positiveOrNegative(-4)); // Negative
}

Ответ 6

Другое возможное решение:

boolean isPositive(int n) {
  return n > ((n + 1) % n);
}

Это не работает для 0.

---- EDIT -----

Новый алгоритм:

String isPositive(int n) {
  String[] results = {"-", "", "+"};
  return results[1+(1+((n+1)%n)*((n-1)%n))/n];
}

Он по-прежнему не работает для 0.

Ответ 7

Люди, это не очень сложно, не нужно сдвигать биты или делать странные вызовы, просто используйте метод signum в классе Math!; Р

http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#signum%28float%29