JavaScript와 IEEE 754

JavaScript는 표준에서 숫자 타입은 IEEE 754-2008, 64 bit format을 따른다고 명시돼있다. 따라서 숫자 타입의 연산도 IEEE 754-2008을 따를 거로 생각했다. 하지만 ECMAScript 명세에서 NaN이나 Infinity를 포함한 연산에 대해 다른 결과를 내도록 정의한다.

그 대표적인 경우가 1-1이다. IEEE 754-2008는 지수를 계산하는 방법을 3가지 정의한다. 첫 번째는 pown으로 지수가 정수인 경우에 대해 정의돼있고, 두 번째 pow는 밑과 지수가 모든 실수인 경우 사용할 수 있도록 정의돼 있고, 마지막은 powr으로 밑이 0 이상의 실수인 경우에 대해서 정의돼 있다. 우선 첫 번째인 pown는 지수가 가 되지 못하므로 관심 대상이 아니다. 다른 두 지수 함수인 powpowr1에 대해 다른 결과를 내도록 정의한다. pow1을 리턴하고, powrinvalid operator exception을 발생하도록 정의했다. 사실 이는 양쪽 다 이상한 것은 아니다. limx1x1에 수렴하지만 1 자체는 부정이기 때문에 1인 경우와 invalid operator exception이 발생하는 경우 양쪽 모두 말이 되기 때문이다. 그렇다면 IEEE 754-2008은 -1를 어떻게 정의할까?

이 경우 밑이 0보다 작으므로 pow만이 유효한 함수고, 이에 대해서 1을 리턴하도록 정의했다. limx-1x는 발산하고, -1는 부정이기 때문에 이는 수학적으로 올바른 정의가 아니고, IEEE 754에서 어떻게 이렇게 정했는지는 모르겠다. 역사적인 이유이거나 이렇게 할 경우 구현이 편해지기 때문일 것인데 혹시 정확한 이유를 알고 있는 사람이 있으면 알려주기 바란다.

ECMAScript에서는 1-1의 연산에 대해서 NaN을 리턴하도록 정의했다. 이는 ECMAScript는 1997년 만들어졌다. 즉, 아직 IEEE 754-2008이 나오기 전이었고 그 당시는 가 지수인 것에 대해 어떻게 계산해야 하는지 표준이 없었다. 그래서 ±1x일 경우 부정이라고 하는 수학적 성질을 따라 NaN이라고 정하였고, format은 IEEE 754-2008을 쓰기로 한 지금도 NaN을 리턴하도록 정해진 것이다.

또 한 가지 다른 점은 나머지 연산이다. 나머지는 xy로 나눴을 때, x-q*y로 정의된다. 이는 xy가 둘 다 양수일 경우 명확하지만, 둘 중 하나라도 음수가 되면 q를 정하는 다양한 수가 나올 수 있다. IEEE 754-2008은 이에 대해서 단순한 솔루션을 제시한다. round(x / y)q로 삼는 것이다. 이는 간단하게 구현할 수 있지만, 일반적으로 예상하는 나머지가 나오지 않는 경우가 많아 많은 언어에서 float division은 다른 방식으로 정의하여 사용한다. 이는 ECMAScript도 마찬가지다. ECMAScript는 floor(abs(x / y))를 절댓값으로 가지고, xy의 sign이 같으면 양수, 다르면 음수인 값을 q로 삼는다.

댓글

댓글 쓰기

이 블로그의 인기 게시물

[C++] enum class - 안전하고 쓰기 쉬운 enum

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

RAII는 무엇인가

[Python] cache 데코레이터로 최적화하기

[Web] SpeechSynthesis - TTS API