Как определить, является ли число положительным или отрицательным? - PullRequest
56 голосов
/ 22 октября 2010

Меня спросили в интервью, как определить, является ли число положительным или отрицательным. Правила таковы, что мы не должны использовать условные операторы, такие как < и >, встроенные в функции Java (например, substring, indexOf, charAt и startsWith), без регулярных выражений или API .

Я сделал несколько домашних заданий по этому вопросу, код приведен ниже, но он работает только для целочисленного типа. Но они попросили меня написать общий код, который работает для float, double и long.

 // This might not be better way!!

 S.O.P ((( number >> 31 ) & 1) == 1 ? "- ve number " : "+ve number );

есть идеи с вашей стороны?

Ответы [ 33 ]

66 голосов
/ 22 октября 2010

Целочисленные случаи просты.Двойной регистр сложнее, пока вы не вспомните о бесконечностях.

Примечание. Если вы считаете двойные константы «частью API», вы можете заменить их переполненными выражениями, такими как 1E308 * 2.

* 1005.*
36 голосов
/ 22 октября 2010

Это ужасный способ уволить вас с любой работы ...

Это зависит от того, получите ли вы исключение переполнения стека [или как там его называет Java] ... И оно будет работать только для положительных чисел, которые не отклоняются от 0, как сумасшедшие.

Отрицательные числа хороши, так как вы переполнитесь до положительного, а затем в конечном итоге получите исключение переполнения стека [которое вернет false, или «да, это отрицательно»]

Boolean isPositive<T>(T a)
{
  if(a == 0) return true;
  else
  {
    try
    {
      return isPositive(a-1);
    }catch(StackOverflowException e)
    {
      return false; //It went way down there and eventually went kaboom
    }
  }
}
17 голосов
/ 22 октября 2010

Это будет работать только для всего, кроме [0..2]

boolean isPositive = (n % (n - 1)) * n == n;

Вы можете сделать лучшее решение, как это (работает за исключением [0..1])

boolean isPositive = ((n % (n - 0.5)) * n) / 0.5 == n;

Вы можете получить лучшую точность, изменив часть 0.5 на 2 ^ m (m integer):

boolean isPositive = ((n % (n - 0.03125)) * n) / 0.03125 == n;
8 голосов
/ 22 октября 2010

Вы можете сделать что-то вроде этого:

((long) (num * 1E308 * 1E308) >> 63) == 0 ? "+ve" : "-ve"

Основная идея здесь заключается в том, что мы приводим к длинному и проверяем значение старшего значащего бита.Так как double / float между -1 и 0 округляется до нуля при приведении к long, мы умножаем на большие двойные значения, так что отрицательный float / double будет меньше -1.Два умножения требуются из-за существования субнормалей (хотя на самом деле оно не должно быть таким большим).

5 голосов
/ 22 октября 2010

Как насчет этого?

return ((num + "").charAt(0) == '-');
3 голосов
/ 22 октября 2010
// Returns 0 if positive, nonzero if negative
public long sign(long value) {
    return value & 0x8000000000000000L;
}

Звоните как:

long val1 = ...;
double val2 = ...;
float val3 = ...;
int val4 = ...;

sign((long) valN);

Преобразование из типа double / float / integer в long должно сохранять знак, если не фактическое значение ...

3 голосов
/ 25 октября 2010

Вы говорите

, мы не должны использовать условные операторы

Но это требование к хитрости, потому что == также является условным оператором.Существует также один, встроенный в циклы ? :, while и for.Таким образом, почти все не смогли дать ответ, отвечающий всем требованиям.

Единственный способ построить решение без условного оператора - это использовать таблицу поиска по сравнению с одним из решений других людей, которые можно свести к0/1 или символ перед выполнением условия.

Вот ответы, которые, я думаю, могут сработать в сравнении с таблицей поиска:

  • Набб
  • СтивенSchlansker
  • Деннис Чунг
  • Гари Роу
2 голосов
/ 04 августа 2015

Этот код охватывает все случаи и типы:

public static boolean isNegative(Number number) {
    return (Double.doubleToLongBits(number.doubleValue()) & Long.MIN_VALUE) == Long.MIN_VALUE;
}

Этот метод принимает любой из классов-оболочек (Integer, Long, Float и Double) и благодаря автоматическомупомещает в коробку любой из примитивных числовых типов (int, long, float и double) и просто проверяет, установлен ли старший бит, который во всех типах является знаковым битом.

Возвращает true когда передано любое из:

  • любой отрицательный int / Integer
  • любой отрицательный long / Long
  • любойотрицательный float / Float
  • любой отрицательный double / Double
  • Double.NEGATIVE_INFINITY
  • Float.NEGATIVE_INFINITY

и false в противном случае.

2 голосов
/ 18 ноября 2010

В этом решении используется модуль. И да, это также работает для 0.5 (тесты приведены ниже, в основном методе).

public class Num {

    public static int sign(long x) {
        if (x == 0L || x == 1L) return (int) x;
        return x == Long.MIN_VALUE || x % (x - 1L) == x ? -1 : 1;
    }

    public static int sign(double x) {
        if (x != x) throw new IllegalArgumentException("NaN");
        if (x == 0.d || x == 1.d) return (int) x;
        if (x == Double.POSITIVE_INFINITY) return 1;
        if (x == Double.NEGATIVE_INFINITY) return -1;
        return x % (x - 1.d) == x ? -1 : 1;
    }

    public static int sign(int x) {
        return Num.sign((long)x);
    }

    public static int sign(float x) {
        return Num.sign((double)x);
    }

    public static void main(String args[]) {

        System.out.println(Num.sign(Integer.MAX_VALUE)); // 1
        System.out.println(Num.sign(1)); // 1
        System.out.println(Num.sign(0)); // 0
        System.out.println(Num.sign(-1)); // -1
        System.out.println(Num.sign(Integer.MIN_VALUE)); // -1

        System.out.println(Num.sign(Long.MAX_VALUE)); // 1
        System.out.println(Num.sign(1L)); // 1
        System.out.println(Num.sign(0L)); // 0
        System.out.println(Num.sign(-1L)); // -1
        System.out.println(Num.sign(Long.MIN_VALUE)); // -1

        System.out.println(Num.sign(Double.POSITIVE_INFINITY)); // 1
        System.out.println(Num.sign(Double.MAX_VALUE)); // 1
        System.out.println(Num.sign(0.5d)); // 1
        System.out.println(Num.sign(0.d)); // 0
        System.out.println(Num.sign(-0.5d)); // -1
        System.out.println(Num.sign(Double.MIN_VALUE)); // -1
        System.out.println(Num.sign(Double.NEGATIVE_INFINITY)); // -1

        System.out.println(Num.sign(Float.POSITIVE_INFINITY)); // 1
        System.out.println(Num.sign(Float.MAX_VALUE)); // 1
        System.out.println(Num.sign(0.5f)); // 1
        System.out.println(Num.sign(0.f)); // 0
        System.out.println(Num.sign(-0.5f)); // -1
        System.out.println(Num.sign(Float.MIN_VALUE)); // -1
        System.out.println(Num.sign(Float.NEGATIVE_INFINITY)); // -1
        System.out.println(Num.sign(Float.NaN)); // Throws an exception

    }
}
1 голос
/ 22 октября 2010

Если это правильный ответ

boolean IsNegative(char[] v) throws NullPointerException, ArrayIndexOutOfBoundException
{ 
  return v[0]=='-'; 
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...