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

하지만이 부정확성의 원인이 무엇인지 모르겠습니다. 부동 숫자에 반올림 문제가 많은 이유는 무엇인가요?

댓글

  • 정확히 말하자면 ‘ 대부분의 사람들이 걱정하는 반올림으로 인한 오류 가 아닙니다. 이진 부동 소수점 반올림이 직관적이지 않은 방식으로 작동한다는 사실은 ‘입니다. 십진수 표현으로 전환하면 반올림이보다 직관적 인 방식으로 작동 할 수 있지만 그 대가로 거의 항상 상대 오차를 증가 하게됩니다 (또는 보상을 위해 저장 공간을 늘려야 함).
  • 가장 일반적인 혼란을 해결하기위한 나의 시도 : floating-point-gui.de
  • @DanielPryden의 의미를 생각합니다. ” [고정 소수점] 표현으로 전환하면 반올림이보다 직관적 인 방식으로 작동 할 수 있습니다 … ” . ‘의 고정 또는 부동 소수점 숫자가 둘 중 하나의 유한 단어 너비인지에 관계없이 반올림 문제가 발생 합니다. 이는 ‘ 부동 소수점을 사용할 때 반올림 오류의 크기가 일반적으로 반올림되는 숫자의 크기에 거의 비례한다는 것입니다. (정말 작아지고 ” 비정규 화 된 ” 숫자를 제외하고)
  • @robert : That ‘ 정확히 제가 언급 한 내용이 아닙니다. 대부분의 사람들이 부동 소수점에 직면하는 ” 오류 “는 ‘와 관련이 없습니다. 부동 소수점 그 자체로 ‘ 기준입니다. IEEE-754 부동 소수점과 복식은 2 진법의 지수를 사용합니다. 즉, 분수는 10의 음의 거듭 제곱 (1/2, 1/16, 1/1024 등)이 아닌 음의 2의 거듭 제곱 (1/2, 1/16, 1/1024 등)으로 반올림됩니다. 10, 1/1000 등) 이로 인해 0.1을 0.1000001로 반올림하는 것과 같은 직관적이지 않은 결과와 유사한 문제가 발생합니다.
  • 10 진수로 부동 소수점 숫자를 수행 할 수 있습니다. 즉 ‘ .NET ‘의 decimal 유형이 작동하는 방식입니다. 반면에 고정 소수점은 다릅니다. 범위가 제한되어있는 한 고정 소수점이 좋은 대답입니다. 그러나 제한적인 범위는 고정 소수점을 많은 수학적 응용 프로그램에 적합하지 않게 만들고 그 결과 고정 소수점 숫자의 구현이 하드웨어에서 잘 최적화되지 않는 경우가 많습니다.

답변

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

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

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

댓글

  • 10 진수로 종료하지 마십시오 ‘ 2 진수로 종료하지 마십시오. 특히 0.1은 2 진수로 반복되는 숫자이므로 부동 소수점 2 진수는 정확히 0.1을 나타낼 수 없습니다.
  • 부동 포인트는 ‘ 많은 소수 자릿수에만 유용하지 않습니다. 32 비트 정수는 약 40 억까지만 셀 수 있지만 32 비트 부동 소수점은 거의 무한대로 클 수 있습니다.
  • 특히 유한 소수로 표현할 수있는 분수는 분모 ‘ 소인수 분해에 2와 5 만 포함 된 분수입니다 (예 : 3/10 및 7/25 , 하지만 11/18). 이진법으로 이동하면 5의 인수를 잃게되므로 이원 적 합리적 (예 : 1/4, 3/128) 만 정확하게 표현할 수 있습니다.

답변

주로 반올림 오류는 모든 실수의 무한대 은 단일 부동 소수점 변수 와 같은 작은 메모리 조각은 말할 것도없고 컴퓨터의 유한 메모리 로 표현 될 수 없으므로 저장된 많은 숫자는 표현하려는 숫자의 근사치입니다.

제한된 수의 값만 있기 때문에 아니요 근사치이며 근사치와 다른 숫자 사이의 모든 연산은 근사치가되며 반올림 오류는 거의 불가피합니다 .

중요 문제는 문제를 일으킬 가능성이있는시기를 파악 하고 위험을 완화하기위한 조치를 취 하는 것입니다.


David Goldberg “의 필수 모든 컴퓨터 과학자 t는 부동 소수점 연산에 대해 알아야합니다. (Sun / Oracle에서 수치의 부록으로 다시 게시 함) Computation Guide ), thorsten 에서 언급 한 ACCU 저널 오버로드

a> 는 iv id = “725e5c176e에 대한 Richard Harris 의 훌륭한 기사 시리즈를 실행했습니다. “> 플로팅 포인트 블루스 .

시리즈는 다음으로 시작되었습니다.

Numerical co mputing에는 많은 함정이 있습니다. Richard Harris는 은색 총알을 찾기 시작합니다.

숫자 오류의 드래곤은 잠에서 깨지는 경우가 많지 않지만 부주의하게 접근하면 부주의 한 프로그래머의 계산에 치명적인 피해를 입힐 수 있습니다.

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

이 시리즈의 기사에서 우리는 탐구 할 것입니다. 부동 소수점 산술과 더 안전한 대체물로 제안 된 몇 가지 기술을 대조하는 수치 계산의 세계. 우리는 드래곤의 영토가 실제로 멀리 도달하고 있으며 일반적으로 드래곤을 두려워한다면 조심스럽게 밟아야한다는 것을 알게 될 것입니다. 엄청난 관심.

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

이보다 더 깊이 읽지 않으면 부동 소수점 숫자와 관련된 문제에 대한 탁월한 근거를 갖게됩니다. .

더 많은 것을 알고 싶으면

그런 다음 Calculus Blues

치료를 돕기 위해 전환합니다. ul>

  • [Insert Algorithm Here]가 미적분 블루스를 치료하지 못하는 이유 오버로드 104 의 div id = “e516e5ed90”> ( pdf , p22-24).
  • 유한 차이가 미적분 블루스를 치료하지 못하는 이유 iv 오버로드 105 의 id = “e516e5ed90”> ( pdf , p5-12).
  • 다항 근사법이 미적분학 블루스를 치료하지 못하는 이유 in 오버로드 106 ( pdf , p16-25).
  • 컴퓨터 대수가 미적분학 블루스를 치료하지 못하는 이유 in 오버로드 107 ( pdf , p15-20).
  • 그리고 마지막으로 중요한 것은

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

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


    그러므로 댓글에 언급 된대로 :

    내 블로그 www.thusspakeak.com 에서 thusspakeak.com/ak/2013/06 .

    댓글

    • 저는 기사의 저자로서 ‘ 내 블로그 www.thusspakeak.com에서 thusspakeak.com/ak/2013/06 .
    • @ thusspakea.k에게 감사합니다. ‘ 메모를 추가했습니다. 내 대답에, 그리고 이러한 상호 작용 요소는 매우 잘 작동합니다.

    답변

    글쎄요, thorsten 에는 최종 링크 가 있습니다. 추가하겠습니다.

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

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

    댓글

    • 추가 할 사항 : ARPREC 또는 decNumber와 같은 임의 정밀도 수학 패키지입니다.
    • 나는 ‘ t 십진수 (이진수와 반대)가 분자와 같은 정수 값에 많은 이점을 제공합니다. 분수의 분모. 둘 중 하나는 정확한 정수 값을 저장할 수 있으며 바이너리가 더 효율적입니다. 입력과 출력을 앞뒤로 변환하는 데는 ‘ 약간의 비용이 있지만, ‘ 물리적 비용으로 인해 휩쓸 릴 가능성이 높습니다. I / O 수행.

    답변

    불안정한 알고리즘의 개념은 지금까지 언급되지 않은 것 같습니다. 조건이 나쁜 문제 . 초보 수치 학자에게는 더 빈번한 함정 인 것처럼 보이므로 전자를 먼저 다루겠습니다.

    (상호) 황금 비율의 거듭 제곱 계산 고려 φ=0.61803…; 가능한 한 가지 방법은 φ^0=1 및 iv id = “로 시작하는 재귀 공식 φ^n=φ^(n-2)-φ^(n-1)를 사용하는 것입니다. 748c911069 “>

    . 선호하는 컴퓨팅 환경에서이 재귀를 실행하고 결과를 정확하게 평가 된 힘과 비교하면 유효 숫자가 느리게 침식되는 것을 발견 할 수 있습니다. 예를 들어 Mathematica 에서 일어나는 일은 다음과 같습니다.

    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 value 7.071019424062048 *^-9). 따라서 알고리즘이 불안정하므로이 재귀 공식을 부정확 한 산술에 사용해서는 안됩니다. 재귀 공식의 내재 된 본질 :이 재귀에 대한 “붕괴”및 “성장”솔루션이 있으며, 대체 “성장”솔루션이있을 때 순방향 솔루션으로 “붕괴”솔루션을 계산하려고하면 수치 적 슬픔을 구걸합니다. 따라서 자신의 수치 알고리즘이 안정적인지 확인해야합니다.

    이제 조건이 나쁜 문제의 개념을 살펴 보겠습니다. 안정적인 방법이있을지라도 수치 적으로 보면 문제가 될 수 있습니다. 당신의 알고리즘으로 해결할 수 없습니다. 이것은 해결 방법이 아니라 문제 자체의 결함입니다. 숫자의 표준 예는 소위 “Hilbert 행렬”을 포함하는 선형 방정식의 해입니다.

    Hilbert 행렬

    The 행렬은 조건이 나쁜 행렬의 표준 예입니다. 큰 힐베르트 행렬로 시스템을 풀려고하면 부정확 한 솔루션이 반환 될 수 있습니다.

    여기에서 “ 수학 데모 : 정확한 산술 결과 비교

    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의 인용문을 남겨 드리겠습니다.

    인생은 우리에게 상태가 좋지 않은 문제를 던질 수 있지만 불안정한 알고리즘에 만족할 이유가 없습니다.

    답변

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

    또는 즉 1/10은 분모가 2의 거듭 제곱 인 분수로 변환됩니다 (이는 부동 소수점 숫자가 본질적인 것입니다).

    주석

    • 정확히 사실이 아닙니다 : 0.5 0.25는 2 진수로 표현할 수 있습니다. ” 모든 10 진수가 아닌 10 진수 “를 의미한다고 생각합니다.
    • 더 정확하게. 모든 분수가 부동 소수점 표기법을 사용하여 정확하게 표현 될 수있는 것은 아닙니다 (즉,. 2 진법과 10 진법 모두이 문제가 있습니다). 십진수로 9*3.3333333를 시도하고이를 9*3 1/3
    • 와 비교하십시오.

    • 이것은 부동 소수점의 가장 일반적인 소스입니다. 착란. .1 + .1 != .2는 10 진수가 아닌 부동 소수점 바이너리 인코딩을 사용하기 때문입니다.
    • @SeanMcMillan : 그리고 1.0/3.0*3.0 != 1.0, -포인트 바이너리 인코딩이 사용됩니다. 삼진법이 아닙니다.

    답변

    수학에는 유리수가 무한히 많습니다. . 32 비트 변수는 2 32 다른 값만 가질 수 있고 64 비트 변수는 2 64 값만 가질 수 있습니다. 따라서 정확한 표현이없는 유리수는 무한히 많습니다.

    우리는 1/3 또는 1/100을 완벽하게 표현할 수있는 계획을 세울 수 있습니다. 많은 실용적인 목적에서 이것은 “별로 유용하지 않다”는 것이 밝혀졌습니다. 한 가지 큰 예외가 있습니다. 금융에서는 소수가 종종 나타납니다. 금융은 본질적으로 물리적 활동이 아니라 인간 활동이기 때문입니다.

    따라서 우리는 보통 이진 부동 소수점을 사용하고 이진으로 표현할 수없는 값을 반올림하도록 선택합니다. 그러나 금융에서는 때때로 소수점 부동 소수점을 선택하고 값을 가장 가까운 소수점 값으로 반올림합니다. .

    댓글

    • 더 나쁘게도 무한한 (아마도 무한한) 양의 메모리를 사용하면 모든 합리성을 나타낼 수 있습니다. 실수를 표현하는 데 충분합니다. 더 나쁜 것은 거의 모든 실수가 계산 가능한 숫자가 아니라는 것입니다. 유한 한 양의 메모리로 할 수있는 최선의 방법은 실수의 유한 범위 하위 집합을 근사하는 것입니다.
    • @Kevin : ‘ 실수의 작은 부분 집합 (측정 값이 0 인 부분 집합) 인 계산 가능한 숫자에 대해 이야기하고 있습니다.
    • +1 가장 기본적인 설명 : ‘ 제한된 수의 비트로 무한한 양의 숫자를 나타내려고합니다.
    • @DavidHammen : 계산 가능한 숫자는 아주 작은 하위 집합입니다 ( 측정 값 0)의 실수-그러나 프로그램에서 작업 할 ‘ 모든 숫자는 정의상 계산 가능합니다.
    • @Giorgio : If 올바른 표현을 선택하면 2의 제곱근을 표현할 수 있습니다 (예 : "√2" 문자열). (내 예전 HP-48 계산기는 정확히 그것을 할 수 있었고, 그 값을 제곱하면 정확히 2.0가되었습니다.) 모든 것을 표현할 수있는 실수는 셀 수없이 무한합니다. 유한 표현-그러나 어떤 계산도 원칙적으로 표현할 수없는 숫자를 산출 할 수 없습니다. 실제로 이진 부동 소수점은 상징적 표현에 비해 빠른 속도와 작은 저장 공간의 이점으로 표현 가능한 숫자 집합을 크게 제한합니다.

    Answer

    내가 생각하는 부동 소수점 숫자의 유일한 “반올림 문제”는 이동 평균 필터입니다.

    $$ \ 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]) \ \ end {align} $$

    노이즈가 쌓이면 현재 샘플에 추가하는 $ x [n] $이 향후 $ N $ 샘플을 뺄 $ x [nN] $와 정확히 일치하는지 확인해야합니다. 그렇지 않다면 다른 점은 지연 선에 갇혀 나오지 않는 작은 똥입니다. 이는이 이동 평균 필터가 실제로 $ z = 1 $에서 약간 안정적인 극점을 갖고 내부를 취소하는 0을 갖는 IIR로 구축 되었기 때문입니다. 그러나 그것은 적분기이고 통합되고 완전히 제거되지 않은 모든 쓰레기는 적분기 합계에 영원히 존재할 것입니다. 고정 소수점은 부동 소수점 숫자와 동일한 문제를 갖지 않습니다.

    댓글

    • 안녕하세요. ‘ prog.SE 포럼에서 $ LaTeX $ 수학 마크 업이 작동하지 않나요 ??? div id = “0934d2d03f”>

    정말 절름발이입니다 ‘ t.

  • meta.SO 및 연결된 질문
  • 답글 남기기

    이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다