+0과 -0이 동일합니까?


171

관통 읽기 인 ECMAScript 5.1 규격 , +0-0구별된다.

그렇다면 왜 +0 === -0평가 true합니까?



6
참고 ES2015에 당신이 사용할 수있는 Object.is+0과 -0 구별하기
벤자민 Gruenbaum

JS의 David Flanagan 인용 최종 안내서 : 언더 플로는 숫자 연산의 결과가 가장 작은 숫자보다 0에 가까울 때 발생합니다. 이 경우 JavaScript는 0을 반환합니다. 음수에서 언더 플로가 발생하면 JavaScript는 "음수 0"이라는 특수 값을 반환합니다.
RBT

답변:


193

JavaScript는 IEEE 754 표준 을 사용 하여 숫자를 나타냅니다. 에서 위키 백과 :

부호있는 0 은 연관된 부호와 함께 0 입니다. 일반적인 산술에서는 −0 = +0 = 0입니다. 그러나 계산에서 일부 숫자 표현은 종종 -0 (음수 0)+0 (양수 0)으로 표시되는 두 개의 0을 허용합니다 . 이것은 정수의 부호있는 숫자 표현과 대부분의 부동 소수점 숫자 표현에서 발생합니다. 숫자 0은 일반적으로 +0으로 인코딩되지만 +0 또는 -0으로 표시 될 수 있습니다.

부동 소수점 산술에 대한 IEEE 754 표준 (현재 부동 소수점 숫자를 지원하는 대부분의 컴퓨터 및 프로그래밍 언어에서 사용)에는 +0과 -0이 모두 필요합니다. 0은 1 / -0 = -∞ 및 1 / + 0 = + ∞의 확장 실수 라인의 변형으로 간주 될 수 있으며, 0으로 나눈 값은 ± 0 / ± 0 및 ± ∞ / ± ∞에 대해서만 정의되지 않습니다. .

이 기사에는 다른 표현에 대한 추가 정보가 들어 있습니다.

이것이 기술적으로 두 제로를 구별해야하는 이유입니다.

그러나 +0 === -0true로 평가됩니다. 왜 그런 겁니까 (...) ?

이 동작은 섹션 11.9.6 , 엄격한 평등 비교 알고리즘 (부분적으로 강조 )에 명시 적으로 정의되어 있습니다 .

x === ywhere xyare 값은 비교 에서 true 또는 false를 생성 합니다 . 이러한 비교는 다음과 같이 수행됩니다.

(...)

  • Type (x)가 숫자이면

    1. x가 NaN이면 false를 반환합니다.
    2. y가 NaN이면 false를 반환합니다.
    3. x가 y와 같은 숫자 값이면 true를 반환합니다.
    4. x가 +0이고 y가 −0이면 true를 반환합니다.
    5. x가 -0이고 y가 +0이면 true를 반환합니다.
    6. 거짓을 돌려줍니다.

(...)

( +0 == -0btw도 마찬가지 입니다.)

논리적으로 취급 +0하고 -0평등 한 것으로 보입니다 . 그렇지 않으면 우리는 이것을 코드에서 고려해야하며 개인적으로는 그렇게하고 싶지 않습니다.)


노트 :

ES2015는 새로운 비교 방법을 도입했습니다 Object.is. Object.is명시 적 구별 -0+0:

Object.is(-0, +0); // false

15
참으로 1/0 === Infinity; // true1/-0 === -Infinity; // true.
user113716

48
우리는 그래서 1 === 1하고 +0 === -0있지만 1/+0 !== 1/-0. 얼마나 이상해!
Randomblue

8
@ 랜덤 : 나는 그것이 +0 !== -0실제로 문제를 일으킬 수있는;) 보다 낫다고 생각합니다 .
Felix Kling

@FelixKling 또는 0 !== +0/ 0 !== -0, 실제로 문제가 발생할 수도 있습니다!
Yanick Rochon

5
실제로이 동작 모델은 수학 계산을 제한합니다. 예를 들어 함수 1 / x는 0의 무한대 값을 갖지만, 음의 양의 양수에서 0에 가까워지면 분리됩니다. 전자의 경우 결과는 + inf이고 후자의 경우 -inf입니다.
Agoston Horvath

19

@ user113716의 의견을 간과했기 때문에 이것을 답변으로 추가하겠습니다.

다음을 수행하여 -0을 테스트 할 수 있습니다.

function isMinusZero(value) {
  return 1/value === -Infinity;
}

isMinusZero(0); // false
isMinusZero(-0); // true

6
== 0도 확인해야 할 경우 위의 isMinusZero (-1e-323)는 true를 반환합니다!
Chris

1
@Chris, 배정 밀도 지수의 한계는 e±308숫자가 비정규 화 된 형식으로 만 표현 될 수 있으며 구현에 따라 지원 위치에 대한 의견이 다릅니다. 요점은 일부 부동 소수점 모드의 일부 컴퓨터에서는 숫자가 -0비정규 화 된 숫자로 표시되고 다른 숫자는 비정규 화 된 숫자로 표시됩니다 0.000000000000001e-308. 그런 수레, 너무 재미
weaknespase

이것은 다른 언어에서도 작동 할 수 있습니다 (C 테스트를 거쳤
으며이

11

+0과 -0이 실제로 다르게 동작하는 예제를 보았습니다.

Math.atan2(0, 0);  //returns 0
Math.atan2(0, -0); //returns Pi

-0.0001과 같은 음수에서 Math.round를 사용하는 경우에도 실제로는 -0이되고 위에 표시된대로 일부 후속 계산을 망칠 수 있습니다.

이 문제를 해결하는 빠르고 더러운 방법은 다음과 같이 smth를 수행하는 것입니다.

if (x==0) x=0;

또는 그냥 :

x+=0;

-0 인 경우 숫자를 +0으로 변환합니다.


감사. 0을 추가하면 내가 겪은 문제를 어떻게 해결할 수 있습니까? "다른 모든 방법이 실패하면 0을 추가하십시오." 인생에 대한 교훈.
Microsis

방금 Math.atan (y / x)에서도이 문제가 발생했습니다. x는 -0 인 경우 잘못된 대답을 제공한다는 점을 제외하고 (아마도 놀랍게도) 긍정적 또는 부정적으로 무한한 "y / x"를 처리 할 수 ​​있습니다. "x"를 "(x + 0)"으로 바꾸면 문제가 해결됩니다.
Jacob C.는 Reinstate Monica가

5

에서 IEEE 754 표준 자바 스크립트의 형식 번호를 나타내는 데 사용되는, 부호가 비트에 의해 표현된다 (1 음의 번호를 나타낸다).

결과적으로를 포함하여 각 표현 가능한 숫자에 대해 음수 값과 양수 값이 모두 존재합니다 0.

이 이유는 둘 다 -0+0존재한다.


3
2의 보수는 부호에 비트를 사용하지만 하나의 0 만 있습니다 (긍정).
Felix Kling

1
예. 그러나 2의 보수에서 음수 비트도 값의 일부이므로 음수 비트를 설정하면 더 이상 0이 아닙니다.
Arnaud Le Blanc

3

원래 제목에 답하기 Are +0 and -0 the same?:

brainslugs83(by by answer Spudley)는 JS의 +0과 -0이 함수와 동일하게 구현되지 않은 중요한 경우를 지적했습니다.

var sign = function(x) {
    return 1 / x === 1 / Math.abs(x);
}

표준 이외 Math.sign의 올바른 부호 +0 및 -0을 반환합니다.


2

0에는 두 가지 가능한 값 (비트 표현)이 있습니다. 이는 고유하지 않습니다. 특히 부동 소수점 숫자에서이 문제가 발생할 수 있습니다. 부동 소수점 숫자는 실제로 일종의 수식으로 저장되기 때문입니다.

정수도 별도의 방식으로 저장할 수 있습니다. 추가 부호 비트가있는 숫자 값을 가질 수 있으므로 16 비트 공간에서 15 비트 정수 값과 부호 비트를 저장할 수 있습니다. 이 표현에서 값 1000 (16 진) 및 0000은 모두 0이지만 그 중 하나는 +0이고 다른 하나는 -0입니다.

정수 값에서 1을 빼서 피할 수 있으므로 -1에서 -2 ^ 16 사이의 범위에 있지만 불편합니다.

더 일반적인 접근 방식은 정수를 '두 개의 보수'에 저장하는 것이지만 ECMAscript는 그렇지 않은 것으로 보입니다. 이 방법에서 숫자의 범위는 0000-7FFF 양수입니다. 음수는 FFFF (-1)에서 8000까지입니다.

물론 동일한 규칙이 더 큰 정수에도 적용되지만 F가 마모되는 것을 원하지 않습니다. ;)


4
하지만 +0 === -0조금 이상하지 않습니까? 지금 우리가 가지고 있기 때문에 1 === 1하고 +0 === -0있지만 1/+0 !== 1/-0...
Randomblue

2
물론 +0은 -0입니다. 둘 다 아무것도 아닙니다. 그러나 + 무한대와-무한대 사이에는 큰 차이가 있습니다. 이러한 무한대 숫자는 ECMA가 +0과 -1을 모두 지원하는 이유 일 수도 있습니다.
GolezTrol

+0 === -0두 비트 표현이 다르더라도 이유를 설명하지 않습니다 .
Randomblue

1
+0은 -0은 0, 아무것도, 나다, niente입니다. 그것들이 동일하다는 것이 합리적입니다. 왜 하늘색입니까? 표현은 다르지만 4 + 3도 1 + 6과 같습니다. 그것들은 다른 표현 (따라서 다른 비트 값)을 가지고 있지만, 비교할 때 그것들은 동일한 0으로 처리됩니다.
GolezTrol

1
그들은 동일 하지 않습니다 . 이를 보여주는 예제는 stackoverflow.com/questions/7223717/differentiating-0-and-0 을 참조하십시오 .
Randomblue

2

Object.is+0과 -0을 구별 하는 데 사용할 수 있습니다 NaN==NaN.

Object.is(+0,-0) //false

Object.is(NaN,NaN) //true

1

나는 엄격한 평등 비교 방법 ( '===')을 비난 할 것입니다. 섹션 4d를보십시오 여기에 이미지 설명을 입력하십시오

사양 에 대한 7.2.13 엄격한 평등 비교 참조


0

Wikipedia에는이 현상을 설명하는 좋은 기사가 있습니다. http://en.wikipedia.org/wiki/Signed_zero

간단히 말해서 +0과 -0 모두 IEEE 부동 소수점 사양에 정의되어 있습니다. 둘 다 기술적으로 부호가없는 0과 정수로 구별됩니다. 이는 정수이지만 실제로는 모두 0으로 평가되므로 모든 실제적인 목적으로 구별을 무시할 수 있습니다.


2
그것은 완전히 정확하지는 않습니다-예를 들어 1 / -0 == 1/0은 자바 스크립트에서 false로 평가됩니다. IEEE 754에는 "부호없는 정수 0"과 같은 개념이 없으므로 마법의 부호없는 0으로 "평가"되지 않습니다.
BrainSlugs83
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.