programing

숫자가 양수인지 음수인지 확인하는 방법은 무엇입니까?

nasanasas 2020. 12. 27. 11:04
반응형

숫자가 양수인지 음수인지 확인하는 방법은 무엇입니까?


인터뷰에서 숫자가 양수인지 음수인지 확인하는 방법에 대해 질문을 받았습니다. 규칙은 우리가 같은 조건 연산자를 사용하지 않도록 있습니다 <, 그리고 >자바 기능 내장, (같은 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 );

당신 편에서 어떤 아이디어라도?


정수 케이스는 쉽습니다. 무한에 대해 기억할 때까지 이중 사례는 더 까다 롭습니다.

참고 : 이중 상수 "api의 일부"를 고려하는 경우이를과 같은 오버플로 식으로 대체 할 수 있습니다 1E308 * 2.

int sign(int i) {
    if (i == 0) return 0;
    if (i >> 31 != 0) return -1;
    return +1;
}
int sign(long i) {
    if (i == 0) return 0;
    if (i >> 63 != 0) return -1;
    return +1;
}
int sign(double f) {
    if (f != f) throw new IllegalArgumentException("NaN");
    if (f == 0) return 0;
    f *= Double.POSITIVE_INFINITY;
    if (f == Double.POSITIVE_INFINITY) return +1;
    if (f == Double.NEGATIVE_INFINITY) return -1;

    //this should never be reached, but I've been wrong before...
    throw new IllegalArgumentException("Unfathomed double");
}

다음은 어떤 직업에서든 해고 될 수있는 끔찍한 접근 방식입니다 ...

Stack Overflow Exception [또는 Java가 호출하는 모든 항목]이 발생하는 경우에 따라 달라집니다. 그리고 미친 듯이 0에서 벗어나지 않는 양수에 대해서만 작동합니다.

음수는 괜찮습니다. 양수로 오버플로 한 다음 결국 스택 오버플로 예외가 발생하므로 [거짓 또는 "예, 음수입니다"를 반환합니다.]

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
    }
  }
}

[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 정수)와 같이 변경하면 더 나은 정밀도를 얻을 수 있습니다.

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

다음과 같이 할 수 있습니다.

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

여기서 주된 아이디어는 long으로 캐스팅하고 최상위 비트의 값을 확인하는 것입니다. -1과 0 사이의 double / float는 long으로 캐스트 될 때 0으로 반올림되므로 큰 double을 곱하여 음의 float / double이 -1보다 작아집니다. 비정규 가 존재하기 때문에 두 번의 곱셈이 필요합니다 (그렇게 필요는 없습니다).


이건 어때?

return ((num + "").charAt(0) == '-');

// 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으로 변환하면 실제 값이 아니라면 부호를 유지해야합니다.


당신은 말한다

조건부 연산자를 사용해서는 안됩니다.

그러나 이것은 ==조건부 연산자 이기 때문에 트릭 요구 사항 입니다. 또한 내장 한이 ? :, while그리고 for루프. 따라서 거의 모든 사람들이 모든 요구 사항을 충족하는 답변을 제공하지 못했습니다.

조건 연산자없이 솔루션을 빌드하는 유일한 방법은 조건이 충족되기 전에 0/1 또는 문자로 요약 될 수있는 몇 가지 다른 사람들의 솔루션 중 하나와 비교표를 사용하는 것입니다.

다음은 룩업 테이블과 비교하여 작동 할 것이라고 생각하는 답변입니다.

  • Nabb
  • 스티븐 슐 랜스 커
  • 데니스 청
  • 게리 로우

이 솔루션은 모듈러스를 사용합니다. 그리고 예, 그것은 또한 작동합니다 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

    }
}

이 코드는 모든 경우와 유형을 다룹니다.

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

이 방법은 래퍼 클래스 (의 수락 Integer, Long, FloatDouble자동 권투 원시 숫자 유형을 (를) 감사를 int, long, float그리고 double이 모든 종류의 부호 비트 인 하이 비트, 설정) 간단하게 확인합니다.

다음 true중 하나를 전달하면 반환 됩니다.

  • 모든 부정적인 int/Integer
  • 모든 부정적인 long/Long
  • 모든 부정적인 float/Float
  • 모든 부정적인 double/Double
  • Double.NEGATIVE_INFINITY
  • Float.NEGATIVE_INFINITY

그리고 false그렇지 않으면.


테스트되지 않았지만 내 아이디어를 보여줍니다.

boolean IsNegative<T>(T v) {
  return (v & ((T)-1));
}

나는 당신이 어떤 유형으로 번호를 얻을 수 있는지 모르기 때문에 나에게 임의적 인 것처럼 보이지만 Abs (number)! = number를 확인하는 것은 어떻습니까? 어쩌면 && 숫자! = 0


정수는 사소합니다. 이것은 이미 알고 있습니다. 깊은 문제는 부동 소수점 값을 처리하는 방법입니다. 그 시점에서 부동 소수점 값이 실제로 작동하는 방식에 대해 조금 더 알아야합니다.

키는 Double.doubleToLongBits () 이며 숫자의 IEEE 표현을 얻을 수 있습니다. (이 방법은 NaN 값을 다루는 약간의 마법과 함께 실제로 직접 캐스트입니다.) double이 long으로 변환되면 0x8000000000000000L을 마스크로 사용하여 부호 비트를 선택할 수 있습니다. 0이면 값은 양수이고 1이면 음수입니다.


유효한 답변 인 경우

boolean IsNegative(char[] v) throws NullPointerException, ArrayIndexOutOfBoundException
{ 
  return v[0]=='-'; 
} 

내가 생각할 수있는 또 하나의 옵션

private static boolean isPositive(Object numberObject) {
Long number = Long.valueOf(numberObject.toString());
return Math.sqrt((number * number)) != number;
}

 private static boolean isPositive(Object numberObject) {
Long number = Long.valueOf(numberObject.toString());
long signedLeftShifteredNumber = number << 1; // Signed left shift
long unsignedRightShifterNumber = signedLeftShifteredNumber >>> 1; // Unsigned right shift
return unsignedRightShifterNumber == number;
}

이것은 대략 ItzWarty의 답변을 기반으로하지만 로그온 시간에 실행됩니다! 주의 사항 : 정수에서만 작동합니다.

Boolean isPositive(int a)
{
  if(a == -1) return false;
  if(a == 0) return false;
  if(a == 1) return true;
  return isPositive(a/2);
}

매우 간단한 해결책이 있다고 생각합니다.

public boolean isPositive(int|float|double|long i){
    return (((i-i)==0)? true : false);
}

내가 틀렸다면 말해줘!


코드없이 이것을 시도하십시오. (x-SQRT(x^2))/(2*x)


조건문을 사용하여 작성한 다음 생성 된 어셈블리 코드를 살펴보십시오.


왜 숫자의 제곱근을 구하지 않습니까? 음수 인 경우-java는 오류를 발생시키고 처리합니다.

         try {
            d = Math.sqrt(THE_NUMBER);
         }
         catch ( ArithmeticException e ) {
            console.putln("Number is negative.");
         }

Java가 숫자 값을 정확히 어떻게 강제하는지는 모르겠지만 의사 코드를 입력하면 대답은 매우 간단합니다 (자세한 내용은 귀하에게 맡깁니다).

sign(x) := (x == 0) ? 0 : (x/x)

경우처럼 "=="를 사용할 수있는 경우 배열 인덱스가 범위를 벗어난 경우 예외가 발생한다는 사실을 이용하여 이와 같은 작업을 수행 할 수 있습니다. 코드는 double 용이지만 모든 숫자 유형을 double로 캐스트 할 수 있습니다 (여기서는 최종 정밀도 손실은 전혀 중요하지 않습니다).

프로세스 (값을] -2.0; -1.0] union [1.0; 2.0 [)과 작은 테스트 드라이버로 설명하기 위해 주석을 추가했습니다.

class T {

   public static boolean positive(double f)
   {
       final boolean pos0[] = {true};
       final boolean posn[] = {false, true};

       if (f == 0.0)
           return true;

       while (true) {

           // If f is in ]-1.0; 1.0[, multiply it by 2 and restart.
           try {
               if (pos0[(int) f]) {
                   f *= 2.0;
                   continue;
               }
           } catch (Exception e) {
           }

           // If f is in ]-2.0; -1.0] U [1.0; 2.0[, return the proper answer.
           try {
               return posn[(int) ((f+1.5)/2)];
           } catch (Exception e) {
           }

           // f is outside ]-2.0; 2.0[, divide by 2 and restart.
           f /= 2.0;

       }

   }

   static void check(double f)
   {
       System.out.println(f + " -> " + positive(f));
   }

   public static void main(String args[])
   {
       for (double i = -10.0; i <= 10.0; i++)
           check(i);
       check(-1e24);
       check(-1e-24);
       check(1e-24);
       check(1e24);
   }

출력은 다음과 같습니다.

-10.0 -> false
-9.0 -> false
-8.0 -> false
-7.0 -> false
-6.0 -> false
-5.0 -> false
-4.0 -> false
-3.0 -> false
-2.0 -> false
-1.0 -> false
0.0 -> true
1.0 -> true
2.0 -> true
3.0 -> true
4.0 -> true
5.0 -> true
6.0 -> true
7.0 -> true
8.0 -> true
9.0 -> true
10.0 -> true
-1.0E24 -> false
-1.0E-24 -> false
1.0E-24 -> true
1.0E24 -> true

비효율적이지만 여기서는 중요하지 않다고 생각합니다. (저는 또한 Java에 대해 약간 녹슬 었습니다. 이것이 다소 정확한 구문이기를 바랍니다.)

boolean isPositive = false;

int n = (int)(x * x);
while (n-- != 0)
{
    if ((int)(--x) == 0)
    {
        isPositive = true;
        break;
    }
}

이것은 x대부분의 x * x경우 (항상 양수) 감소하고 x0과 같지 않으면 음수 여야 시작하기 때문에 작동합니다. 경우 x, 다른 한편으로는, 어떤 점에서 0 일, 그것은에 postive되어 있어야합니다.

이 발생할 것이라고 참고 isPositivefalse0.

추신 : 분명히, 이것은 (int)(x * x)오버플로 될 것이기 때문에 매우 큰 숫자에서는 작동하지 않습니다 .


음, 캐스팅을 활용하면 (실제 값이 무엇인지 신경 쓰지 않기 때문에) 아마도 다음과 같은 것이 효과가있을 것입니다. 실제 구현은 API 규칙을 위반하지 않습니다. 나는 {-1, + 1} 문제 도메인에 대한 @chris의 코멘트에 비추어 메서드 이름을 좀 더 분명하게 만들기 위해 이것을 편집했습니다. 본질적으로이 문제는 float 및 double 프리미티브의 기본 비트 구조를 참조하는 Float 또는 Double 내의 API 메서드에 의존하지 않고는 해결할 수없는 것으로 보입니다.

다른 사람들이 말했듯이 : 어리석은 인터뷰 질문. Grr.

public class SignDemo {

  public static boolean isNegative(byte x) {
    return (( x >> 7 ) & 1) == 1;
  }

  public static boolean isNegative(short x) {
    return (( x >> 15 ) & 1) == 1;
  }

  public static boolean isNegative(int x) {
    return (( x >> 31 ) & 1) == 1;
  }

  public static boolean isNegative(long x) {
    return (( x >> 63 ) & 1) == 1;
  }

  public static boolean isNegative(float x) {
    return isNegative((int)x);
  }

  public static boolean isNegative(double x) {
    return isNegative((long)x);
  }

  public static void main(String[] args) {


    // byte
    System.out.printf("Byte %b%n",isNegative((byte)1));
    System.out.printf("Byte %b%n",isNegative((byte)-1));

    // short
    System.out.printf("Short %b%n",isNegative((short)1));
    System.out.printf("Short %b%n",isNegative((short)-1));

    // int
    System.out.printf("Int %b%n",isNegative(1));
    System.out.printf("Int %b%n",isNegative(-1));

    // long
    System.out.printf("Long %b%n",isNegative(1L));
    System.out.printf("Long %b%n",isNegative(-1L));

    // float
    System.out.printf("Float %b%n",isNegative(Float.MAX_VALUE));
    System.out.printf("Float %b%n",isNegative(Float.NEGATIVE_INFINITY));

    // double
    System.out.printf("Double %b%n",isNegative(Double.MAX_VALUE));
    System.out.printf("Double %b%n",isNegative(Double.NEGATIVE_INFINITY));

    // interesting cases
    // This will fail because we can't get to the float bits without an API and
    // casting will round to zero
    System.out.printf("{-1,1} (fail) %b%n",isNegative(-0.5f));

  }

}

이 솔루션은 조건부 연산자를 사용하지 않지만 두 가지 예외를 포착하는 데 의존합니다.

나누기 오류는 원래 "음수"인 숫자와 동일합니다. 또는 숫자가 결국 행성에서 떨어지고 양수인 경우 StackOverFlow 예외가 발생합니다.

public static boolean isPositive( f)
       {
           int x;
           try {
               x = 1/((int)f + 1);
               return isPositive(x+1);
           } catch (StackOverFlow Error e) {
               return true;

           } catch (Zero Division Error e) {
               return false;
           }


   }

What about the following?

T sign(T x) {
    if(x==0) return 0;
    return x/Math.abs(x);
}

Should work for every type T...

Alternatively, one can define abs(x) as Math.sqrt(x*x), and if that is also cheating, implement your own square root function...


if (((Double)calcYourDouble()).toString().contains("-"))
        doThis();
else doThat();

Combined generics with double API. Guess it's a bit of cheating, but at least we need to write only one method:

static <T extends Number> boolean isNegative(T number)
{       
    return ((number.doubleValue() * Double.POSITIVE_INFINITY) == Double.NEGATIVE_INFINITY);
}

Two simple solutions. Works also for infinities and numbers -1 <= r <= 1 Will return "positive" for NaNs.

String positiveOrNegative(double number){
    return (((int)(number/0.0))>>31 == 0)? "positive" : "negative";
}

String positiveOrNegative(double number){
    return (number==0 || ((int)(number-1.0))>>31==0)? "positive" : "negative";
}

There is a function is the math library called signnum.

http://www.tutorialspoint.com/java/lang/math_signum_float.htm http://www.tutorialspoint.com/java/lang/math_signum_double.htm


It's easy to do this like

private static boolean isNeg(T l) {
        return (Math.abs(l-1)>Math.abs(l));
 }

ReferenceURL : https://stackoverflow.com/questions/3994531/how-to-determine-if-a-number-is-positive-or-negative

반응형