You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Box-Mueller算法出现对数函数负/零参数运行时错误的解决咨询

Fixing the Negative/Zero Log Argument Error in Your Box-Mueller Fortran Code

Hey there, let's break down why you're hitting that runtime error and how to fix it quickly.

The Root Cause

Your error stems from a logical mistake in the do while loop condition meant to filter valid points for the Box-Mueller algorithm. Let’s look at that problematic line:

Do while (w>=1.0.and.w<0.0)

This condition is impossible to satisfy—w can’t be both ≥1 and <0 at the same time! The loop never runs, so you end up using invalid values of w (either your initial w=2 or occasionally w=0 if r1 and r2 both land on 0) when calculating log(w). When w=0, log(w) throws the "negative or zero argument" error; when w>1, -2*log(w) becomes negative, which would cause another error when taking the square root later.

The Fix

The Box-Mueller algorithm requires generating points strictly inside the unit circle, meaning w = r1² + r2² must be 0 < w < 1. Update your loop condition to keep generating new r1 and r2 until w falls into this valid range:

Do while (w >= 1.0 .or. w <= 0.0)

This way, if w is too large (≥1) or zero (the only invalid non-positive value possible here), the loop will re-run to get valid values.

Corrected Code Snippet

Here’s the fixed section of your program:

Do j=0,n
    ! Reset w to an invalid value to ensure we enter the loop
    w = 2.0
    Do while (w >= 1.0 .or. w <= 0.0)
        Call random_number(r1)
        Call random_number(r2)
        r1 = 2.0*r1 - 1.0
        r2 = 2.0*r2 - 1.0
        w = r1*r1 + r2*r2
    End do
    w = sqrt((-2.0*log(w))/w)
    r1 = r1*w
    r2 = r2*w
    If(mod(j,2)==0) then
        w=r1
    Else if(mod(j,2)==1) then
        w=r2
    End if
    fx(j+1)=fx(j)+w*sqrt(2.0*D*dt)
    ! Rest of your code...
End do

Bonus Optimization (Optional)

Right now, you generate a new pair of Gaussian numbers every j iteration but only use one each time. You can reuse the second number to cut down on random_number calls:

! Track if we have an unused Gaussian number from the last generation
logical :: has_spare = .false.
real :: spare_gauss

Do j=0,n
    if (.not. has_spare) then
        w = 2.0
        Do while (w >= 1.0 .or. w <= 0.0)
            Call random_number(r1)
            Call random_number(r2)
            r1 = 2.0*r1 - 1.0
            r2 = 2.0*r2 - 1.0
            w = r1*r1 + r2*r2
        End do
        w = sqrt((-2.0*log(w))/w)
        r1 = r1*w
        r2 = r2*w
        spare_gauss = r2
        has_spare = .true.
        w = r1
    else
        w = spare_gauss
        has_spare = .false.
    end if
    ! Rest of your code for updating fx(j+1)...
End do

This is just a performance tweak—your core error is fixed with the loop condition change.

Why This Works

By fixing the loop condition, you ensure w is always in the (0,1) range before calculating log(w). This eliminates invalid arguments to the logarithm routine and guarantees the square root in the Box-Mueller formula uses a positive value.

内容的提问来源于stack exchange,提问作者SchrodingersCat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:02:55