Проверять положительные или отрицательные значения без использования условных операторов в 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