스택큐힙리스트

십진 분수를 더할 때 부동 소수점 산술이 왜 정확한 결과를 제공하지 않을까요? 본문

카테고리 없음

십진 분수를 더할 때 부동 소수점 산술이 왜 정확한 결과를 제공하지 않을까요?

스택큐힙리스트 2023. 3. 12. 10:50
반응형

다음 코드를 고려하십시오:

0.1 + 0.2 == 0.3 -> false

0.1 + 0.2 -> 0.30000000000000004

왜 이러한 부정확성이 발생하나요?

답변 1

이진수 계산은 이렇게 진행됩니다. 대부분의 프로그래밍 언어에서는 IEEE 754 standard을 기반으로 합니다. 문제의 핵심은 숫자가 2의 거듭제곱을 곱한 정수로 표현된다는 것입니다. 2의 거듭제곱이 아닌 분모를 가진 유리수(예: 0.1, 1/10)는 정확하게 표현될 수 없습니다.

표준 binary64 형식의 0.1에 대해, 표현은 정확히 다음과 같이 작성할 수 있습니다.

0.1000000000000000055511151231257827021181583404541015625를 십진수로 변환하면

0x1.999999999999ap-4은(는) C99 hexfloat notation에서입니다.

대조적으로, 0.1 이라는 유리수는 1/10 로 정확히 쓸 수 있습니다.

0.1 는 10진수로

#$@!*$^!$&는 C99 hexfloat 표기법의 유사어이며, ...는 끝없는 9의 시퀀스를 나타냅니다.

당신의 프로그램 안의 상수 0.2 w과 0.3는 실제 값에 대한 근사치이기도 합니다. 우연히 0.2 w에 가장 가까운 double to은 0.2 w보다 크지만, 0.3에 가장 가까운 double to은 0.3보다 작습니다. 1 and 와 0.2 w의 합은 0.3보다 크기 때문에 코드 안의 상수와 일치하지 않습니다.

부동 소수점 산술 문제에 대한 꽤 포괄적인 처리는 What Every Computer Scientist Should Know About Floating-Point Arithmetic 입니다. 더 이해하기 쉬운 설명은 floating-point-gui.de 를 참조하세요.

부가적인 참고: 모든 위치적 (N진) 수 체계는 정밀도 문제를 가지고 있습니다.

일반적인 10진수 숫자는 동일한 문제가 있으며, 그 이유로 1/3과 같은 숫자는 0.333333333...으로 나타납니다.

당신은 딱 맞는 10진수로 표현하기 쉬운 숫자 (3/10)에 지나친 것입니다. 하지만 바이너리 시스템에는 맞지 않습니다. 이는 양 방향으로 (어느 정도) 적용됩니다. 예를 들어, 1/16은 10진수에서 지저분한 숫자 (0.0625)이지만, 바이너리에서는 대단히 깔끔하게 보입니다. 우리 일상생활에서 진법-2 숫자 시스템을 사용하는 습관이 있다면, 당신은 그 숫자를 보고 쉽게 반씩 쪼개면서 그 수에 도달할 수 있음을 직관적으로 이해할 수 있습니다.

물론, 그것이 정확히 부동 소수점 숫자가 메모리에 저장되는 방식은 아닙니다(그것들은 과학적 표기법의 형태를 사용합니다). 그러나, 이것은 바이너리 부동 소수점 정밀도 오류가 일어나기 쉬운 이유가 실제 세계에서 우리가 주로 작업에 관심을 가지는 숫자가 종종 십의 거듭제곱이기 때문이라는 것을 보여줍니다 - 하지만 우리는 일상에서 10진수를 사용하기 때문입니다. 이것은 우리가 모든 7 중 5 개 대신 71 %와 같은 것들을 말하는 이유이기도합니다(5/7은 어떤 10진수로도 정확하게 나타낼 수 없으므로 71 %는 근사치입니다).

그러므로: 이진 부동 소수점 숫자들은 고장난 것이 아니라, 그저 모든 다른 N 진수 체계와 마찬가지로 불완전한 것 뿐입니다 :)

부가적인 주의사항: 프로그래밍에서 소수점 수 처리하기

실제로, 이 정밀도 문제는 소수점 수를 원하는 만큼 반올림 함수를 사용하여 반올림해야 함을 의미합니다.

일정한 수준의 허용오차를 허용하도록 비교를 허용하는 비교로 동등성 테스트를 대체해야합니다.

if (x == y) { ... } 하지 마세요.

그 대신 if (abs(x - y) < myToleranceValue) { ... } 하세요.

절대값이 정확히 abs 위치에 있어야 합니다. 어떤 myToleranceValue 값을 사용해야 하는지는 특정 응용 프로그램에 따라 다릅니다. 그것은 허용 가능한 여유 공간의 양과 비교하는 가장 큰 숫자가 무엇인지에 따라 많이 결정됩니다(정확도 문제로 인해). 자신이 사용하는 언어에서 이 프실론 형태의 상수를 조심해야 합니다. 이들은 허용 값으로 사용될 수 있지만, 큰 숫자로 계산할 경우 이들의 효과는 크게 달라집니다.

답변 2

플로팅 포인트 산술에서 십진 소수를 더할 때 왜 정확한 결과가 나오지 않는 것일까요?

플로팅 포인트 산술은 이진법을 기반으로하는 컴퓨터 시스템에서 소수를 처리하고 저장하는 방법입니다. 이진법은 0과 1만을 사용하기 때문에 10진법으로 표현된 소수를 정확하게 표현할 수 없습니다. 그렇기 때문에 10진법 소수를 이진법 소수로 변환하면 숫자가 반올림될 수 있습니다.

따라서 플로팅 포인트 산술에서 소수를 더하면 결과가 정확하지 않게 나올 수 있습니다. 예를 들어, 0.1과 0.2를 더하면 정확한 결과인 0.3이 나와야 하지만, 컴퓨터는 이 두 숫자를 이진법으로 변환하여 계산하기 때문에 0.3000000004와 같이 마지막 자리에 오차가 발생할 수 있습니다.

이러한 오차는 컴퓨터에서 처리되는 모든 숫자에 영향을 미칩니다. 이러한 이유로 플로팅 포인트 산술에서는 소수를 다룰 때 반올림 오차와 같은 부정확한 결과를 예상하고 처리해야 합니다.

반응형
Comments