[java] +0 및 -0은 int 및 float 데이터에 대해 다른 동작을 보여줍니다.

나는이 게시물을 부정적이고 양의 0으로 읽었습니다 .

제공해야합니다 나의 이해 다음 코드 truetrue A 출력 등.

그러나 결과를 제공 false하고 true있습니다.

음수 0을 양수 0과 비교하고 있습니다.

public class Test {
     public static void main(String[] args) {
            float f = 0;
            float f2 = -f;
            Float F = new Float(f);
            Float F1 = new Float(f2);
            System.out.println(F1.equals(F));

            int i = 0;
            int i2 = -i;
            Integer I = new Integer(i);
            Integer I1 = new Integer(i2);
            System.out.println(I1.equals(I));
      }
  }

0 Integer과에 대해 다른 동작을하는 이유는 무엇 Float입니까?



답변

Int와 float는 Java와는 매우 다릅니다. 정수는 2의 보수 로 인코딩되며 단일 0 값을 갖습니다. Float 는 IEEE 754 ( float의 경우 32 비트 변형 , double의 경우 64 비트 변형 )를 사용합니다. IEEE 754는 다소 복잡하지만이 답변의 목적을 위해 세 개의 섹션이 있으며 그 중 첫 번째 부분은 부호 비트라는 것을 알아야합니다. 즉, 모든 플로트에는 긍정적이고 부정적인 변형이 있습니다 ¹. 여기에는 0이 포함됩니다. 따라서 float는 실제로 “0”값인 +0과 -0을 갖습니다.

따로, 정수가 사용하는 두 가지 보완은 컴퓨터 과학에서 정수를 인코딩하는 유일한 방법은 아닙니다. 하나의 보수 와 같은 다른 방법이 있지만 +0과 -0을 별개의 값으로 갖는 것과 같은 단점이 있습니다. 😉

float 프리미티브 (및 double)를 비교할 때 Java는 +0과 -0을 동일하게 취급합니다. 그러나 당신이 그것들을 박스에 넣을 때, Java는에 설명 된 것처럼 그것들을 개별적으로 취급합니다 Float#equals. 이것은 equals 메소드가 hashCode구현뿐만 아니라 compareTo(부호있는 값을 포함하여) float 비트를 사용하여 그대로 int로 밀어 넣는 구현 과 일치하게합니다 .

equals / hashCode / compareTo에 대한 다른 옵션을 선택할 수 있었지만 그렇지 않았습니다. 디자인 고려 사항이 무엇인지 잘 모르겠습니다. 그러나 적어도 하나 개의 점에서, Float#equals항상 플로트 원시의에서 분기 거라고 ==: 프리미티브에서, NaN != NaN하지만 모든 개체, o.equals(o)도 참이어야합니다 . 그것은 당신이 있었다면 Float f = Float.NaN, f.equals(f)그래도 의미합니다 f.floatValue() != f.floatValue().


¹ NaN (숫자가 아님) 값에는 부호 비트가 있지만 순서 이외의 다른 의미는 없으며 Java는 순서를 무시합니다.


답변

이것은 Float equals 예외 중 하나입니다

두 가지 예외가 있습니다.

f1이 + 0.0f를 나타내고 f2가 -0.0f를 나타내 거나 그 반대의 경우, 등식 테스트의 값은 false입니다.

이유도 설명되어 있습니다.

이 정의는 해시 테이블이 올바르게 작동하도록합니다.

-0과 0은 Float의 비트 31을 사용하여 다르게 나타납니다.

비트 31 (마스크 0x80000000에 의해 선택된 비트)은 부동 소수점 숫자의 부호를 나타냅니다.

이 경우에는 그렇지 않습니다 Integer


답변

정수의 경우, 2의 칭찬 표현을 사용하므로 정수의 -0과 0 사이에는 차이가 없습니다 . 따라서 정수 예제 ii1정확히 동일합니다.

float의 경우 -0 표현이 있으며 값은 0과 동일하지만 비트 표현은 다릅니다. 따라서 new Float (0f)와 new Float (-0f)는 서로 다른 표현을 갖습니다.

비트 표현의 차이를 볼 수 있습니다.

System.out.println(Float.floatToIntBits(-0f) + ", " + Float.floatToIntBits(0f));

-2147483648, 0

그리고 f선언을 생략하면 -0f정수로 취급되며 출력에 차이가 표시되지 않습니다.


답변