부동 소수점 반올림 오류의 원인은 무엇입니까?


62

부동 소수점 산술에는 정밀도 문제가 있음을 알고 있습니다. 나는 보통 숫자의 고정 소수점 표현으로 바꾸거나 단순히 오류를 무시함으로써 그것들을 극복합니다.

그러나 나는이 부정확의 원인이 무엇인지 모른다. 부동 소수점 숫자에 왜 이렇게 많은 반올림 문제가 있습니까?


28
정확하게 말하면 대부분의 사람들이 걱정하는 반올림으로 인한 오류 는 실제로 이진 부동 소수점 반올림이 직관적이지 않은 방식으로 작동한다는 사실이 아닙니다. 10 진수 표현으로 전환하면 반올림이보다 직관적 인 방식으로 작동 할 수 있지만, 대체적으로 상대 오류를 거의 늘릴 수 있습니다 (또는 저장 공간을 늘려서 보정해야 함).
Daniel Pryden

12
가장 일반적인 혼란을 정리하기 위해 내 시도 : floating-point-gui.de
마이클 Borgwardt

@DanielPryden의 의미는 "[고정 소수점] 표현으로 전환하면 반올림이보다 직관적 인 방식으로 작동 할 수 있습니다 ..."라고 생각 합니다. 어떤 원인 이 고정 또는 부동 소수점 숫자인지, 문제를 반올림하는 것은 하나의 유한 단어 폭이다. 부동 소수점의 경우 반올림 오차의 크기는 일반적으로 반올림되는 숫자의 크기에 대략 비례합니다. (실제로 숫자가 작고 "비정규 화 된"숫자 인 경우 제외)
robert bristow-johnson

@ robert : 정확히 내가 말하는 것은 아닙니다. 대부분의 사람들이 부동 소수점과 마주 치는 "오류"는 부동 소수점 그 자체와 관련이 없으며 기본입니다. IEEE-754 float 및 double은 밑이 2 인 지수를 사용합니다. 즉, 소수는 10의 음의 거듭 제곱이 아니라 2의 음의 거듭 제곱 (1/2, 1/16, 1/1024 등)으로 반올림됩니다. 10, 1/1000 등) 이로 인해 0.1 반올림 0.1000001과 유사한 문제와 같은 직관적이지 않은 결과가 발생합니다.
Daniel Pryden

기본 10에서 부동 소수점 숫자를 수행 할 수 있습니다 decimal. 이것이 .NET 유형의 작동 방식입니다. 반면에 고정 점은 다릅니다. 범위가 제한되는 한 고정 소수점이 정답입니다. 그러나 제한적인 범위는 고정 소수점을 많은 수학적 응용에 부적합하게 만들고 고정 소수점 수의 구현은 종종 하드웨어에서 잘 최적화되지 않습니다.
Daniel Pryden

답변:


82

일부 분수는 반올림없이 표현하기 위해 매우 많은 (또는 무한한) 장소가 필요하기 때문입니다. 이것은 바이너리 나 다른 것만 큼 십진 표기법에도 적용됩니다. 계산에 사용할 소수 자릿수를 제한하고 분수 표기법으로 계산하지 않으려면 간단한 식도 1/3 + 1/3로 반올림해야합니다. 결과적으로 2/3를 쓰는 대신 0.33333 + 0.33333 = 0.66666을 써야하며 이는 2/3과 동일하지 않습니다.

컴퓨터의 경우 자릿수는 메모리 및 CPU 레지스터의 기술적 특성에 따라 제한됩니다. 내부적으로 사용되는 이진 표기법은 더 많은 어려움을 추가합니다. 컴퓨터는 일반적으로 분수 표기법으로 숫자를 표현할 수 없지만 일부 프로그래밍 언어는 이러한 기능을 추가하여 이러한 문제를 어느 정도 피할 수 있습니다.

부동 소수점 산술에 대해 모든 컴퓨터 과학자가 알아야 할 사항


12
에 딱 맞다. 그러나 소수로 끝나는 일부 숫자는 이진수로 끝나지 않습니다. 특히 0.1은 이진수로 되풀이되는 숫자이므로 부동 소수점 이진수는 정확히 0.1을 나타낼 수 없습니다.
Jack Aidley

4
부동 소수점은 소수점 이하 자릿수에만 유용하지 않습니다. 32 비트 정수는 최대 40 억 개까지만 계산할 수 있지만 32 비트 부동 소수점은 거의 무한대가 될 수 있습니다.
Abhi Beckert

7
특히, 유한 소수로 표현할 수있는 분수는 분모의 소인수 분해율이 2와 5 만 포함하는 분수입니다 (예 : 3/10과 7/25는 표현할 수 있지만 11/18은 표현할 수 없음). 이진으로 이동할 때, 우리는 5의 인자를 잃어 버리기 때문에, 이분법적인 합리적 (예 : 1/4, 3/128) 만 정확하게 표현 될 수 있습니다.
David Zhang

70

기본적으로 반올림 오류 는 모든 실수무한대가 단일 부동 소수점 변수 와 같은 작은 메모리 조각은 물론 컴퓨터유한 메모리 로 표현할 수 없으므로 실제로 저장되는 많은 숫자는 근사치입니다. 그들이 나타내는 숫자.

근사값 이 아닌 제한된 수의 값만 있고 근사값과 다른 숫자 사이의 연산으로 근사값이 발생하므로 반올림 오류는 거의 불가피 합니다.

중요한 것은하는 것입니다 그들이 문제가 발생할 가능성이있을 때 실현 하고 위험을 완화하기위한 조치를 취할 .


뿐만 아니라 데이비드 골드버그 의 필수 부동 소수점 연산에 관하여 모든 컴퓨터 과학자가 알아야 할 사항 (자신에 부록으로 썬 / 오라클에 의해 재 게시 수치 계산 가이드 에 의해 언급되었다) 토르스텐ACCU의 저널 과부하가 우수한을 실행 Floating Point Blues 에 대한 Richard Harris 의 기사 시리즈 .

이 시리즈는

수치 컴퓨팅에는 많은 함정이 있습니다. 리차드 해리스는 은색 총알을 찾기 시작합니다.

수치 적 오류의 용은 종종 파자마에서 깨어나지 않지만, 조심스럽게 다가 가면, 때때로 경고하지 않은 프로그래머의 계산에 치명적인 피해를 입게됩니다.

IEEE 754 부동 소수점 산술의 숲에서 우연히 만난 일부 프로그래머들은 동료들에게 그 공정한 땅을 여행하지 않도록 조언합니다.

이 기사 시리즈에서는 수치 계산의 세계를 살펴보고 부동 소수점 산술을보다 안전한 대체 기술로 제안 된 기술과 대조합니다. 우리는 용의 영토가 실제로 다가오고 있다는 사실을 알게 될 것이며, 일반적으로 우리가 그의 파괴적인 관심을 두려워하면 조심스럽게 밟아야한다는 것을 알게 될 것입니다.

Richard는 실수, 이성, 비이성, 대수 및 초월의 분류를 설명하는 것으로 시작합니다. 그런 다음 취소 오류 및 실행 순서 순서로 진행하기 전에 IEEE754 표현을 설명합니다.

이것보다 더 깊이 읽지 않으면 부동 소수점 숫자와 관련된 문제에 대한 훌륭한 접지가 될 것입니다.

당신이 그러나 더 알고 싶은 경우에, 그는 계속합니다

그런 다음 미적분학 블루스 치료에 도움을주기 위해 노력합니다

마지막으로

전체 기사 시리즈는 살펴볼 가치가 있으며, 총 66 페이지로 여전히 Goldberg 논문 의 77 페이지보다 작습니다 .

이 시리즈는 거의 동일한 근거를 다루지 만 Goldberg의 논문 보다 접근하기가 더 쉽다는 것을 알았습니다 . 또한 Richards의 초기 기사를 읽은 후이 초기 기사를 읽은 후에는 Goldberg 논문이 다루지 않은 많은 흥미로운 영역으로 분기되는 논문의 복잡한 부분을 이해하는 것이 더 쉽다는 것을 알았습니다.


따라서 주석에서 언급 한 것처럼 ak :

그 기사의 저자로서 나는 내 블로그에 그들의 대화 형 버전을 만들었다 고 언급하고 싶습니다 www.thusspakeak.com 로 시작 thusspakeak.com/ak/2013/06 .


1
이 기사의 저자로서 나는 내 블로그 www.thusspakeak.com에서 그와 같은 대화식 버전을 만들었 음을 언급하고 싶다 .
따라서

감사합니다 @ thusspakea.k. 내 답변에 메모를 추가했으며 이러한 대화 형 요소가 매우 잘 작동합니다.
마크 부스

12

글쎄, 토르스텐 은 확실한 연결 고리를 가지고 있습니다. 나는 추가 할 것이다 :

모든 형식의 표현에는 일부 숫자에 대한 반올림 오류가 있습니다. 1/3을 IEEE 부동 소수점 또는 10 진수로 표현하십시오. 둘 다 정확하게 할 수는 없습니다. 이것은 귀하의 질문에 대답하는 것 이상이지만,이 경험 법칙을 성공적으로 사용했습니다.

  • 사용자가 입력 한 값을 10 진수로 저장합니다 (거의 확실하게 10 진수로 입력했기 때문에 이진 또는 16 진수를 사용하는 사용자는 거의 없습니다). 그렇게하면 항상 사용자가 입력 한 정확한 표현을 얻을 수 있습니다.
  • 사용자가 입력 한 분수를 저장해야하는 경우 분자 및 분모 (10 진수)도 저장하십시오.
  • 동일한 수량에 대해 여러 측정 단위 (예 : 섭씨 / 화씨)가있는 시스템이 있고 사용자가 둘 다 입력 할 수 있으면 입력 한 값과 입력 한 값을 저장하십시오. 변환하여 다른 이름으로 저장하지 마십시오. 정밀도 / 정확도의 손실없이 할 수없는 한 단일 표현. 모든 계산에 저장된 값 단위를 사용하십시오 .
  • 기계 생성 값을 IEEE 부동 소수점에 저장합니다 (이는 A / D 변환기가있는 아날로그 센서 또는 계산의 반올림 결과와 같은 전자 측정 장치에 의해 생성 된 숫자 일 수 있습니다). 직렬 연결을 통해 센서를 읽고 이미 10 진수 형식 (예 : 18.2 C)으로 값을 제공하는 경우에는 적용되지 않습니다.
  • 은행 계좌 잔고와 같이 사용자가 볼 수있는 총계 등을 10 진수로 저장합니다. 적절하게 반올림하지만 해당 값을 이후의 모든 계산에서 결정적인 값으로 사용하십시오.

ARPREC 또는 decNumber와 같은 임의 정밀도 수학 패키지를 사용하는 것이 좋습니다.
Blrfl

소수 (이진과 반대)는 분수 및 분자의 분모와 같은 정수 값에 많은 이점이 있습니다. 정확한 정수 값을 저장할 수 있으며 이진이 더 효율적입니다. 입출력을 위해 앞뒤로 변환하는 데 약간의 비용이 들지만, 실제로 I / O를 수행하는 비용에 의해 늪이 될 수 있습니다.
Keith Thompson

10

지금까지 언급되지 않은 것은 불안정한 알고리즘 의 개념 과 조건잘못된 문제 입니다. 나는 초보 수치 주의자들에게 더 빈번한 함정 인 것처럼 보이기 때문에 전자를 먼저 다룰 것이다.

(역수) 황금비의 거듭 제곱의 계산을 고려하십시오 φ=0.61803…. 한 가지 가능한 방법은 and로 φ^n=φ^(n-2)-φ^(n-1)시작 하는 재귀 수식을 사용하는 것입니다 . 선호하는 컴퓨팅 환경에서이 재귀를 실행하고 결과를 정확하게 평가 된 검정력과 비교하면 중요한 수치가 느리게 침식됩니다. Mathematica 에서 예를 들면 다음과 같습니다 .φ^0=1φ^1=φ

ph = N[1/GoldenRatio];  
Nest[Append[#1, #1[[-2]] - #1[[-1]]] & , {1, ph}, 50] - ph^Range[0, 51]  
{0., 0., 1.1102230246251565*^-16, -5.551115123125783*^-17, 2.220446049250313*^-16, 
-2.3592239273284576*^-16, 4.85722573273506*^-16, -7.147060721024445*^-16, 
1.2073675392798577*^-15, -1.916869440954372*^-15, 3.1259717037102064*^-15, 
-5.0411064211886014*^-15, 8.16837916750579*^-15, -1.3209051907825398*^-14, 
2.1377864756200182*^-14, -3.458669982359108*^-14, 5.596472721011714*^-14, 
-9.055131861349097*^-14, 1.465160458236081*^-13, -2.370673237795176*^-13, 
3.835834102607072*^-13, -6.206507137114341*^-13, 1.004234127360273*^-12, 
-1.6248848342954435*^-12, 2.6291189633497825*^-12, -4.254003796798193*^-12, 
6.883122762265558*^-12, -1.1137126558640235*^-11, 1.8020249321541067*^-11, 
-2.9157375879969544*^-11, 4.717762520172237*^-11, -7.633500108148015*^-11, 
1.23512626283229*^-10, -1.9984762736468268*^-10, 3.233602536479646*^-10, 
-5.232078810126407*^-10, 8.465681346606119*^-10, -1.3697760156732426*^-9, 
2.216344150333856*^-9, -3.5861201660070964*^-9, 5.802464316340953*^-9, 
-9.388584482348049*^-9, 1.5191048798689004*^-8, -2.457963328103705*^-8, 
3.9770682079726053*^-8, -6.43503153607631*^-8, 1.0412099744048916*^-7, 
-1.6847131280125227*^-7, 2.725923102417414*^-7, -4.4106362304299367*^-7, 
7.136559332847351*^-7, -1.1547195563277288*^-6}

추출 된 결과에 φ^41잘못된 부호가 있으며 심지어 이전에는 계산 된 값과 실제 값 φ^39이 공통으로 숫자 를 공유하지 않습니다 ( 3.484899258054952* ^-9 for the computed version against the true value7.071019424062048 *^-9). 따라서 알고리즘이 불안정하므로이 재귀 공식을 부정확 한 산술에 사용해서는 안됩니다. 이것은 재귀 공식의 고유 한 특성 때문입니다.이 재귀에는 "부패"및 "성장"솔루션이 있으며, 대안적인 "성장"솔루션이있을 때 포워드 솔루션으로 "부패"솔루션을 계산하려고합니다. 수치적인 슬픔을 위해. 따라서 수치 알고리즘이 안정적인지 확인해야합니다.

이제는 조건잘못된 문제 의 개념으로, 수치 적으로 무언가를 수행하는 안정적인 방법이있을지라도 알고리즘으로는 해결할 수없는 문제 일 수 있습니다. 이것은 해결책 자체가 아니라 문제 자체의 결함입니다. 숫자의 표준 예는 소위 "Hilbert matrix"와 관련된 선형 방정식의 솔루션입니다.

힐버트 매트릭스

이 행렬은 조건잘못된 행렬의 정식 예입니다. 힐버트 행렬이 큰 시스템을 해결하려고하면 부정확 한 솔루션이 반환 될 수 있습니다.

다음은 Mathematica 데모입니다. 정확한 산술 결과를 비교하십시오.

Table[LinearSolve[HilbertMatrix[n], HilbertMatrix[n].ConstantArray[1, n]], {n, 2, 12}]
{{1, 1}, {1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 
  1}, {1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1,
   1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}

부정확 한 산술

Table[LinearSolve[N[HilbertMatrix[n]], N[HilbertMatrix[n].ConstantArray[1, n]]], {n, 2, 12}]
{{1., 1.}, {1., 1., 1.}, {1., 1., 1., 1.}, {1., 1., 1., 1., 1.},  
  {1., 1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1., 1.}, 
  {1., 1., 1., 1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1., 1., 1., 1.},  
  {1., 1., 1., 0.99997, 1.00014, 0.999618, 1.00062, 0.9994, 1.00031, 
  0.999931}, {1., 1., 0.999995, 1.00006, 0.999658, 1.00122, 0.997327, 
  1.00367, 0.996932, 1.00143, 0.999717}, {1., 1., 0.999986, 1.00022, 
  0.998241, 1.00831, 0.975462, 1.0466, 0.94311, 1.04312, 0.981529, 
  1.00342}}

( Mathematica 에서 사용해 보았을 경우 , 잘못된 상태가 표시 된다는 경고 메시지가 나타납니다.)

두 경우 모두, 단순히 정밀도를 높이는 것은 치료법이 아닙니다. 피할 수없는 수치의 침식 만 지연시킬 것입니다.

이것이 당신이 직면 할 수있는 것입니다. 해결책은 어려울 수 있습니다. 첫째, 드로잉 보드로 돌아가거나 저널 / 책 / 책을 통해 다른 사람이 자신보다 더 나은 솔루션을 찾았는지 찾아보십시오. 두 번째로, 당신은 문제를 더 다루기 쉬운 것으로 포기하거나 재구성합니다.


Dianne O'Leary의 인용문을 남겨 드리겠습니다.

인생은 우리에게 문제가되는 몇 가지 문제를 던져 줄 수도 있지만 불안정한 알고리즘을 해결해야 할 이유는 없습니다.


9

10 진수 10 진수는 2 진수로 표현할 수 없기 때문에

즉, 1/10을 분모에서 2의 거듭 제곱으로 분수로 변환 할 수 없습니다 (기본적으로 부동 소수점 숫자)


11
정확히 사실이 아닙니다 : 0.5와 0.25는 밑이 2로 표현 될 수 있습니다. "모든 십진수가 아니라"를 의미한다고 생각합니다.
Scott Whitlock

3
좀 더 정확하게. 부동 소수점 표기법을 사용하여 모든 소수를 정확하게 표현할 수있는 것은 아닙니다 (예 :. 시도하고 9*3.3333333십진수로하고 그것을 comapre9*3 1/3
마틴 요크

1
이것이 가장 일반적인 부동 소수점 혼란의 원인입니다. .1 + .1 != .2소수점이 아닌 부동 소수점 이진 인코딩이 사용되기 때문입니다.
Sean McMillan

@SeanMcMillan : 그리고 1.0/3.0*3.0 != 1.0, 삼항이 아닌 부동 소수점 이진 인코딩이 사용되기 때문입니다.
Keith Thompson

8

수학에는 합리적으로 많은 수의 합리적인 숫자가 있습니다. 32 비트 변수는 2 개의 32 개의 다른 값만 가질 수 있고 64 비트 변수는 2 개의 64 개의 값만 가질 수 있습니다. 따라서 정확한 표현이없는 합리적 숫자는 무한히 많습니다.

1/3을 완벽하게 표현하거나 1/100을 표현할 수있는 체계를 생각 해낼 수 있습니다. 많은 실용적인 목적으로 이것은별로 유용하지 않다는 것이 밝혀졌습니다. 한 가지 큰 예외가 있습니다. 재무 분야에서는 소수 부분이 종종 나타납니다. 금융은 본질적으로 물리적 인 활동이 아니라 인간의 활동이기 때문입니다.

따라서 일반적으로 이진 부동 소수점을 사용하고 이진으로 표현할 수없는 모든 값을 반올림합니다. 그러나 재무에서는 때때로 소수점 부동 소수점을 선택하고 값을 가장 가까운 소수점 값으로 반올림합니다.


2
더 나쁜 것은, 무한한 (수적으로 무한한) 메모리 양이 모든 합리적 표현을 가능하게 할 것이지만, 실재를 표현하기에는 충분하지 않을 것입니다. 더 나쁜 것은, 거의 모든 실수는 계산 가능한 숫자가 아닙니다. 유한 한 양의 메모리로 할 수있는 최선의 방법은 유한 범위의 실수의 근사값을 근사화하는 것입니다.
David Hammen

4
@Kevin : 계산 가능한 숫자에 대해 이야기하고 있습니다. 계산 가능한 숫자는 실수의 작은 부분 집합 (계수 0의 부분 집합)입니다.
David Hammen

1
가장 기본적인 설명을 위해 +1 : 유한 비트 수로 무한한 수의 숫자를 나타내려고합니다.
Raku

1
@DavidHammen : 계산 가능한 숫자는 실수의 작은 부분 집합입니다. 그러나 프로그램에서 작업 할 모든 숫자는 정의상 계산 가능합니다.
Keith Thompson

3
@Giorgio : 당신이 바로 그 표현을 선택하는 경우, 2의 제곱근 이다 문자열로, 예를 들어, 표현할 수 "√2". (나의 오래된 HP-48 계산기는 정확히을 할 수 있었고, 그 값을 제곱 정확히 결과 2.0.)에 대한 표현 가능한 실수 만 셀 수있는 무한 있습니다 어떤 있지만 계산은하지 않는 번호를 얻을 수 없습니다 - 유한 표현 원칙적으로 표현할 수 있습니다. 실제로, 이진 부동 소수점은 상징적 표현에 비해 빠른 속도와 작은 저장 공간이라는 이점으로 표현 가능한 숫자 세트를 크게 제한합니다.
Keith Thompson

-2

내가 생각하는 부동 소수점 숫자로 유일하게 확실한 "반올림 문제"는 이동 평균 필터입니다.

$$ \ begin {align} y [n] & = \ frac {1} {N} \ sum \ limits_ {i = 0} ^ {N-1} x [ni] \ & = y [n-1] + \ frac {1} {N} (x [n]-x [nN]) \ \ 끝 {align} $$

노이즈가 발생하지 않고이 작업을 수행하려면 현재 샘플에 추가 한 $ x [n] $가 $ N $ 샘플을 빼는 $ x [nN] $과 정확히 동일해야합니다. 미래. 그렇지 않다면, 다른 점은 지연 라인에 갇히고 결코 나오지 않을 작은 똥입니다. 이는이 이동 평균 필터가 실제로 $ z = 1 $에서 한계 적으로 안정적인 극점과 내부를 취소하는 0을 갖는 IIR로 구축되기 때문입니다. 그러나 그것은 통합 자이며 통합되어 완전히 제거되지 않은 쓰레기는 영원히 통합 자 합계에 존재할 것입니다. 이것은 고정 소수점과 부동 소수점 숫자와 같은 문제가없는 곳입니다.


prog.SE 포럼에서 $ LaTeX $ 수학 마크 업이 작동하지 않습니까 ??? 그렇지 않으면 정말 절름발이입니다.
robert bristow-johnson 5

1
참조 meta.SO에이 와 연결 질문
AakashM
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.