2016-08-08 3 views
0

줄리아에서 웨이브 함수의 확률 밀도를 계산하고 플롯하려고합니다. 나는 다음과 같은 기능을 평가하기위한 줄리아 코드의 작은 조각을 썼다 :줄리아의 exp 함수는 0으로 평가됩니다.

P = A^2 e^{-(\sqrt(Cm)/\hbar)x^2}

줄리아 (불완전) 코드는 다음과 같습니다

set_bigfloat_precision(100) 
A = 10 
C = 5 
m = BigFloat(9.10938356e-31) 
ℏ = BigFloat(1.054571800e-34) 
t = exp(-(sqrt(C * m)/ℏ)) 

내가 t0.000000000000...을 제공 평가의 마지막 행. BigFloat의 정밀도를 설정하려고했습니다. 불운! 내가 도대체 ​​뭘 잘못하고있는 겁니까? 도움말 감사.

+0

수식의 제곱근이 약간 모호합니다. 분수의 분모와 분모를 모두 고려해야하는 것처럼 보입니다. 그러나 당신의 코드에서 분자의 제곱근만을 취하고 있습니다 ... 이것이 문제입니까? –

+0

일반적으로'm = BigFloat (9.10938356e-31)'과 같은 것을 사용하고 싶지는 않습니다. '9.10938356e-31'은 Float64이며, 반올림하고 BigFloat로 바뀌지 만 이미 거기에 Float64 반올림 오류가 발생했을 것입니다. 대신, 보통'parse (BigFloat, "9.10938356e-31")'를 사용하는 것이 더 강력합니다. 나는 당신이 여기에 당신의 실수라고 생각하지 않는다. (왜냐하면 당신이 십진수를 넣었 기 때문이다.) 그러나 가까운 장래에 어떤 에러를 멈출지도 모른다. –

+0

@ColinTBowers 제곱근에 대해 당신이 옳았다는 것을 알 수 있습니다. 편집 됨. 도움을 주셔서 감사합니다. –

답변

6

댓글에서 Chris Rackauckas는 수식을 잘못 입력했다고 지적했습니다.

A = 10 
C = 5 
m = BigFloat(9.10938356e-31) 
h = BigFloat(1.054571800e-34) 

z = -sqrt(C * m)/h 
t = exp(z) 

그래서 z =-2.0237336022083455711032042949257e+19 때문에 매우 약 z=-2e19)

그래서 대략 t=exp(-2e19)을 : 나는이 질문에 대답 할만큼 흥미로웠다 어쨌든

그래서 우리는 우리가 제기하는 것을 볼 수 있습니다 그것을 무너 뜨리는 수 있습니다 생각 (즉 t=1/((e^(2*10^19))) 아주 작은 숫자입니다.

exp(big"-1e+10") = 9.278...e-4342944820exp(big"-1e+18") = 2.233...e-434294481903251828

하고 예, 줄리아는 말한다 고려 : exp(big"-2e+19) = 0.0000

exp(big"-2e+19)은 매우 작은 수이다. 그것은 우리를 문맥에 빠트립니다. 아주 작은 숫자.


그래서 줄리아 당신은 MPFR online을 시도 할 수 BigFloats에 대한 MPFR에 따라 달라집니다. 정밀도 8192 일 때 exp(-2e10)=0 결과가 동일합니다.

이제는 우리가 신경 쓰는 정밀도가 아닙니다. 그러나 지수의 범위는 오히려.

MPFR은 IEEE 스타일의 수레를 사용합니다. 여기에서 precision은 가수의 길이이고 지수는 있습니다. 2^exponent * mantissa

따라서 지수의 범위에는 제한이 있습니다.

참조 : MPFR docs:

기능 : mpfr_exp_t의 mpfr_get_emin (무효) 기능 : mpfr_exp_t mpfr_get_emax (무효) 부동 소수점 변수에 허용

돌아 가기 (현재) 최소 및 최대 지수. 부동 소수점 변수의 가장 작은 양수 값은 1/2의 지수이며, 가장 작은 지수 인으로 증가하며 가장 큰 값은 (1 - ε) 배의 2가 가장 큰 지수로 증가합니다. 엡실론은 고려 된 변수.

이제 julia가이를 최대한으로 설정하여 기본 MPFR 컴파일을 허용합니다. 나는 이것이 설정되어있는 곳을 찾기 위해 MPFR 소스를 파고 있었지만 찾을 수는 없었다. 나는 이것이 Int64가 가질 수있는 최대 결함과 관련이 있다고 생각한다.

Base.MPFR.get_emin() = -4611686018427387903 =typemin(Int64)>>1 + 1

만까지이를 조정할 수 있지만.

어쨌든

0.5*big"2.0"^(Base.MPFR.get_emin()) = 8.5096913117408361391297879096205e-1388255822130839284

하지만 0.5*big"2.0"^(Base.MPFR.get_emin()-1) = 0.00000000000...


이제 우리는 알고

exp(x) = 2^(log(2,e)*x)

그래서 우리가 할 수있는 exp(z) = 2^(log(2,e)*z) 지수 (거친 -2.9e19가) 최소 허용 지수 (대략 -4.3e17)보다 작 그래서 이후 Base.MPFR.get_emin() = -4611686018427387903


log(2,e)*z = -29196304319863382016
. 언더 플로우가 발생합니다.

따라서 0 점을 얻었습니다.

줄리아는 Int128 지수로 MPFR을 재구성 할 수도 있지만 그렇지 않을 수도 있습니다.

아마도 줄리아는 언더 플로 예외를 throw해야합니다. 무료로 Julia Bug Tracker의 문제로보고 해 주시기 바랍니다.

+1

당신은 매우 우아하게 설명했습니다. 아주 친절하게 감사드립니다! 게다가 나는 git에 문제를 열었다. [매우 작은 숫자에 대해서는 exp를 평가할 때 언더 플로우가 발생한다] (https://github.com/JuliaLang/julia/issues/17893) –

관련 문제