관통 읽기 인 ECMAScript 5.1 규격 , +0
과 -0
구별된다.
그렇다면 왜 +0 === -0
평가 true
합니까?
Object.is
+0과 -0 구별하기
관통 읽기 인 ECMAScript 5.1 규격 , +0
과 -0
구별된다.
그렇다면 왜 +0 === -0
평가 true
합니까?
Object.is
+0과 -0 구별하기
답변:
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 === -0
true로 평가됩니다. 왜 그런 겁니까 (...) ?
이 동작은 섹션 11.9.6 , 엄격한 평등 비교 알고리즘 (부분적으로 강조 )에 명시 적으로 정의되어 있습니다 .
x === y
wherex
및y
are 값은 비교 에서 true 또는 false를 생성 합니다 . 이러한 비교는 다음과 같이 수행됩니다.(...)
Type (x)가 숫자이면
- x가 NaN이면 false를 반환합니다.
- y가 NaN이면 false를 반환합니다.
- x가 y와 같은 숫자 값이면 true를 반환합니다.
- x가 +0이고 y가 −0이면 true를 반환합니다.
- x가 -0이고 y가 +0이면 true를 반환합니다.
- 거짓을 돌려줍니다.
(...)
( +0 == -0
btw도 마찬가지 입니다.)
논리적으로 취급 +0
하고 -0
평등 한 것으로 보입니다 . 그렇지 않으면 우리는 이것을 코드에서 고려해야하며 개인적으로는 그렇게하고 싶지 않습니다.)
노트 :
ES2015는 새로운 비교 방법을 도입했습니다 Object.is
. Object.is
명시 적 구별 -0
과 +0
:
Object.is(-0, +0); // false
1/0 === Infinity; // true
와 1/-0 === -Infinity; // true
.
1 === 1
하고 +0 === -0
있지만 1/+0 !== 1/-0
. 얼마나 이상해!
+0 !== -0
실제로 문제를 일으킬 수있는;) 보다 낫다고 생각합니다 .
0 !== +0
/ 0 !== -0
, 실제로 문제가 발생할 수도 있습니다!
@ user113716의 의견을 간과했기 때문에 이것을 답변으로 추가하겠습니다.
다음을 수행하여 -0을 테스트 할 수 있습니다.
function isMinusZero(value) {
return 1/value === -Infinity;
}
isMinusZero(0); // false
isMinusZero(-0); // true
e±308
숫자가 비정규 화 된 형식으로 만 표현 될 수 있으며 구현에 따라 지원 위치에 대한 의견이 다릅니다. 요점은 일부 부동 소수점 모드의 일부 컴퓨터에서는 숫자가 -0
비정규 화 된 숫자로 표시되고 다른 숫자는 비정규 화 된 숫자로 표시됩니다 0.000000000000001e-308
. 그런 수레, 너무 재미
+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으로 변환합니다.
에서 IEEE 754 표준 자바 스크립트의 형식 번호를 나타내는 데 사용되는, 부호가 비트에 의해 표현된다 (1 음의 번호를 나타낸다).
결과적으로를 포함하여 각 표현 가능한 숫자에 대해 음수 값과 양수 값이 모두 존재합니다 0
.
이 이유는 둘 다 -0
와 +0
존재한다.
0에는 두 가지 가능한 값 (비트 표현)이 있습니다. 이는 고유하지 않습니다. 특히 부동 소수점 숫자에서이 문제가 발생할 수 있습니다. 부동 소수점 숫자는 실제로 일종의 수식으로 저장되기 때문입니다.
정수도 별도의 방식으로 저장할 수 있습니다. 추가 부호 비트가있는 숫자 값을 가질 수 있으므로 16 비트 공간에서 15 비트 정수 값과 부호 비트를 저장할 수 있습니다. 이 표현에서 값 1000 (16 진) 및 0000은 모두 0이지만 그 중 하나는 +0이고 다른 하나는 -0입니다.
정수 값에서 1을 빼서 피할 수 있으므로 -1에서 -2 ^ 16 사이의 범위에 있지만 불편합니다.
더 일반적인 접근 방식은 정수를 '두 개의 보수'에 저장하는 것이지만 ECMAscript는 그렇지 않은 것으로 보입니다. 이 방법에서 숫자의 범위는 0000-7FFF 양수입니다. 음수는 FFFF (-1)에서 8000까지입니다.
물론 동일한 규칙이 더 큰 정수에도 적용되지만 F가 마모되는 것을 원하지 않습니다. ;)
+0 === -0
조금 이상하지 않습니까? 지금 우리가 가지고 있기 때문에 1 === 1
하고 +0 === -0
있지만 1/+0 !== 1/-0
...
+0 === -0
두 비트 표현이 다르더라도 이유를 설명하지 않습니다 .
Wikipedia에는이 현상을 설명하는 좋은 기사가 있습니다. http://en.wikipedia.org/wiki/Signed_zero
간단히 말해서 +0과 -0 모두 IEEE 부동 소수점 사양에 정의되어 있습니다. 둘 다 기술적으로 부호가없는 0과 정수로 구별됩니다. 이는 정수이지만 실제로는 모두 0으로 평가되므로 모든 실제적인 목적으로 구별을 무시할 수 있습니다.