Math.pow () (때때로)가 JavaScript에서 **와 같지 않은 이유는 무엇입니까?


118

방금 ( MDN Reference ) a**b의 대안으로 ECMAScript 7 기능 을 발견 했으며 해당 게시물 에서 분명히 다르게 동작 하는 토론을 발견했습니다 . Chrome 55에서 테스트했으며 결과가 다른 것을 확인할 수 있습니다.Math.pow(a,b)

Math.pow(99,99) 보고 3.697296376497263e+197

이므로

99**99 보고 3.697296376497268e+197

차이 로그인 그래서 Math.pow(99,99) - 99**99결과를 -5.311379928167671e+182.

지금까지는 단순히 또 다른 구현이라고 말할 수 있지만 함수로 래핑하면 다시 다르게 동작합니다.

function diff(x) {
  return Math.pow(x,x) - x**x;
}

호출 diff(99)반환 0.

왜 그럴까요?

으로 xszaboj는 지적이이 문제로 좁혀 할 수 있습니다 :

var x = 99;
x**x - 99**99; // Returns -5.311379928167671e+182

7
누군가가 사용한 알고리즘을 다시 작성한 것처럼 들리며 부동 소수점 오류 가 발견되었습니다. 숫자는 어렵습니다 ...
krillgar

4
@krillgar는 합리적으로 들리지만 함수에서 동일한 오류가 발생하지 않는 이유는 무엇입니까?
Thomas Altmann

3
@AndersonPimentel MDN 링크는 호환성 테이블을 가리 킵니다 .
Álvaro González

7
차이점은 다음과 같습니다. var x = 99; x * * x; 및 99 * * 99. 또는 function diff (x) {return 99 * * 99-(x * * x); }; diff (99). 죄송 간격에 대한 코멘트는 두 개의 별 :( 필터
xszaboj

1
@xszaboj 역 따옴표에 코드를 넣어 `likethis`그것을 읽을 수 있도록하고 또한 굵게 / 기울임 문제를 피하기
phuclv

답변:


126

99**99되어 컴파일 시간에 평가 ( "상수 폴딩"), 컴파일러의 pow루틴 로부터 다른 런타임 하나 . 평가할 때 **런타임에, 결과와 동일합니다 Math.pow- 이후 당연 **실제로 컴파일 A를 Math.pow호출 :

console.log(99**99);           // 3.697296376497268e+197
a = 99, b = 99;
console.log(a**b);             // 3.697296376497263e+197
console.log(Math.pow(99, 99)); // 3.697296376497263e+197

사실은

99 99 = 369729637649726772657187905628805440595668764281741102430259972423552570455277523421410650010128232727940978889548326540119429996769494359451621570193644014418071060667659301384999779999159200499899

따라서 첫 번째 결과는 더 나은 근사치이지만 여전히 상수 및 동적 표현 사이에 이러한 불일치가 발생해서는 안됩니다.

이 동작은 V8의 버그처럼 보입니다. 그것은 보고되었다 잘하면 곧 해결 얻을 것이다.


19
그래서 그것은 기본적으로 컴퓨팅으로 성능을 향상시키려는 JS입니다 99**99. Math.pow숫자와 변수에 대해 동일한 출력을 생성하고 생성 **하지 않기 때문에 버그로 간주 될 수 있습니까?
Thomas Altmann

3
@ThomasAltmann : Math.row항상 런타임이며, const 접기는 연산자에 대해서만 수행 할 수 있습니다. 예, 확실히 버그입니다.
georg

11
여기 OP에 의해 사물의 모습 으로 버그 가 기록되었습니다 .
James Thorpe

5
나는 MS 에지를 사용하고, 모든 3 개 결과는 동일합니다 3.697296376497263e+197, 3.697296376497263e+197그리고 3.697296376497263e+197각각. 확실히 Chrome 버그입니다.
Nolonar

4
@ThomasAltmann 상수 접기가 런타임 impl보다 더 나쁜 값을 생성 하면 버그입니다. 런타임보다 더 나은 값을 생성 하면 버그로 간주 될 수도 있고 그렇지 않을 수도 있습니다. 이 경우 더 좋습니다. 올바른 값은 "... 26772 ..."이고 상수 폴딩은 "... 268"(올바르게 반올림)을 생성하며 런타임은 "... 263"(4+ 마지막 장소에있는 단위).
hobbs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.