이 번역 페이지는 최신 내용을 담고 있지 않습니다. 최신 내용을 영문으로 보려면 여기를 클릭하십시오.
반올림 오차를 인식하고 방지하기
값을 수치적으로 근사할 때는 부동소수점 결과가 사용된 정밀도의 영향을 받을 수 있다는 점에 유의하십시오. 또한, 부동소수점 결과에는 반올림 오차가 발생하기 쉽습니다. 다음 접근 방식은 잘못된 결과를 인식하고 방지하는 데 도움이 될 수 있습니다.
가능한 경우 기호 계산 사용하기
정확한 기호 계산은 반올림 오차가 발생하지 않기 때문에 기호적으로 계산을 수행하는 것이 좋습니다. 예를 들어, Symbolic Math Toolbox™에서 표준 수학 상수는 고유한 기호 표현을 갖습니다.
pi sym(pi)
ans = 3.1416 ans = pi
수치 근삿값을 불필요하게 사용하지 마십시오. 부동소수점 숫자는 상수를 근사하지만 그 자체가 상수이지는 않습니다. 이 근삿값을 사용하면 잘못된 결과를 얻을 수 있습니다. 예를 들어, heaviside
특수 함수는 sym(pi)
의 사인과 pi
의 수치 근삿값에 대한 사인에 대해 각기 다른 결과를 반환합니다.
heaviside(sin(sym(pi))) heaviside(sin(pi))
ans = 1/2 ans = 1
정밀도를 높여 계산 수행하기
리만 가설은 리만 제타 함수 ζ(z)의 모든 자명하지 않은 영점이 동일한 실수부 ℜ(z) = 1/2을 갖는다고 가정합니다. 제타 함수의 가능한 영점을 찾기 위해 절댓값 |ζ(1/2 + iy)|를 플로팅합니다. 다음 플롯은 제타 함수 |ζ(1/2 + iy)|의 처음 3개의 자명하지 않은 근을 보여줍니다.
syms y
fplot(abs(zeta(1/2 + i*y)), [0 30])
수치 솔버 vpasolve
를 사용하여 제타 함수의 처음 3개의 영점을 근사합니다.
vpasolve(zeta(1/2 + i*y), y, 15) vpasolve(zeta(1/2 + i*y), y, 20) vpasolve(zeta(1/2 + i*y), y, 25)
ans = 14.134725141734693790457251983562 ans = 21.022039638771554992628479593897 ans = 25.010857580145688763213790992563
이제, 동일한 함수를 사용하되, 실수부를 약간 늘려 보겠습니다. 리만 가설에 따르면 이 함수는 모든 실수 값 y에 대해 영점을 갖지 않습니다. 유효 소수점 자릿수를 10으로 하여 vpasolve
를 사용하면 솔버가 제타 함수에 대해 다음과 같은 (존재하지 않는) 영점을 구합니다.
old = digits; digits(10) vpasolve(zeta(1000000001/2000000000 + i*y), y, 15)
ans = 14.13472514
자릿수를 늘리면 결과가 올바르지 않다는 것을 알 수 있습니다. 제타 함수 는 14 < y < 15에 해당하는 모든 실수 값에 대해 영점을 갖지 않습니다.
digits(15) vpasolve(zeta(1000000001/2000000000 + i*y), y, 15) digits(old)
ans = 14.1347251417347 + 0.000000000499989207306345i
추후 계산을 위해 디폴트 자릿수를 복원합니다.
digits(old)
기호 결과와 수치 결과 비교하기
반정수 인덱스를 갖는 베셀 함수는 정확한 기호 표현식을 반환합니다. 이러한 표현식을 부동소수점 숫자로 근사하면 매우 불안정한 결과가 생성될 수 있습니다. 예를 들어, 다음 베셀 함수에 대한 정확한 기호 표현식은 아래와 같습니다.
B = besselj(53/2, sym(pi))
B = (351*2^(1/2)*(119409675/pi^4 - 20300/pi^2 - 315241542000/pi^6... + 445475704038750/pi^8 - 366812794263762000/pi^10 +... 182947881139051297500/pi^12 - 55720697512636766610000/pi^14... + 10174148683695239020903125/pi^16 - 1060253389142977540073062500/pi^18... + 57306695683177936040949028125/pi^20 - 1331871030107060331702688875000/pi^22... + 8490677816932509614604641578125/pi^24 + 1))/pi^2
vpa
를 사용하여 이 표현식을 10자리 정확도로 근사합니다.
vpa(B, 10)
ans = -2854.225191
이제 부동소수점 파라미터로 베셀 함수를 호출합니다. 이러한 두 근삿값 간의 유의미한 차이는 하나 또는 두 결과 모두가 올바르지 않음을 나타냅니다.
besselj(53/2, pi)
ans = 6.9001e-23
B
에 대한 더 정확한 근삿값을 구하려면 수치 작업 정밀도를 높이십시오.
vpa(B, 50)
ans = 0.000000000000000000000069001456069172842068862232841396473796597233761161
함수 또는 표현식 플로팅하기
결과를 플로팅하면 잘못된 근삿값을 인식하는 데 도움이 될 수 있습니다. 예를 들어, 다음 베셀 함수의 수치 근삿값을 구하면 아래와 같은 결과가 반환됩니다.
B = besselj(53/2, sym(pi)); vpa(B, 10)
ans = -2854.225191
53/2
근방의 x
의 값에 대해 이 베셀 함수를 플로팅합니다. 함수 플롯은 근삿값이 올바르지 않다는 것을 보여줍니다.
syms x
fplot(besselj(x, sym(pi)), [26 27])