+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 x및 yare 값은 비교 에서 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; // true와 1/-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.