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

Python实现D维蒙特卡洛积分结果与精确值不符,求错误排查

问题描述

我正尝试通过蒙特卡洛积分求解如下积分:
积分公式
核心思路是生成N个采样点,按如下公式计算曲线下面积:
面积计算公式
为此我编写了如下Python代码:

import numpy as np
from sympy import symbols, integrate     

def f(x,D):                             
  return D*(x**2)

for i in range(1, 9):                    
  x = symbols('x')                      
  print("D为{}时积分的精确数学值为:{}\n".format(i, integrate(f(x,i),(x, 0,1)).evalf(2))) 

print("*************************************************************************\n")

N = 10**4
for j in range(1,9):
  ans = 0
  n_tot = N
  n_below_curve = 0
  for i in range(N):
    x0=np.random.uniform(0,1)
    y0=np.random.uniform(0,1)
    if (f(x0,j) <= y0):
      n_below_curve += 1
  ans = ( n_below_curve / n_tot ) * (1*1)
  print("D为{}时的积分结果为:{}\n".format(j, ans))

运行输出如下:

D为1时积分的精确数学值为:0.33 

D为2时积分的精确数学值为:0.67 

D为3时积分的精确数学值为:1.0 

D为4时积分的精确数学值为:1.3 

D为5时积分的精确数学值为:1.7 

D为6时积分的精确数学值为:2.0 

D为7时积分的精确数学值为:2.3 

D为8时积分的精确数学值为:2.7 

************************************************************************* 

D为1时的积分结果为:0.6635 

D为2时的积分结果为:0.4681 

D为3时的积分结果为:0.3823 

D为4时的积分结果为:0.3321 

D为5时的积分结果为:0.2978 

D为6时的积分结果为:0.269 

D为7时的积分结果为:0.252 

D为8时的积分结果为:0.2372 

对比精确值和蒙特卡洛输出结果,积分完全失效,请问代码错误出在哪里?


错误原因和修正方案

代码存在两个核心逻辑错误:

  1. 投点判断条件写反
    你要统计的是落在曲线下方的点,也就是采样的y值小于等于函数值,即y0 <= f(x0,j),但你写的是f(x0,j) <= y0,刚好统计了曲线上方的点,这也是D=1时结果约为0.66,刚好是1减去精确值0.33的原因。

  2. y轴采样范围不匹配函数最大值
    你的被积函数f(x,D) = Dx²在积分区间[0,1]的最大值为D(当x=1时取得),但你将y的采样范围限制在了[0,1],当D>1时,大量函数值超过了1,这部分区间的点你根本无法正确统计,自然结果完全偏离。同时计算面积时,采样矩形的面积应该是x区间长度乘以y区间长度,也就是1D,而非你写的11。


修正后的代码
import numpy as np
from sympy import symbols, integrate     

def f(x,D):                             
  return D*(x**2)

for i in range(1, 9):                    
  x = symbols('x')                      
  print("D为{}时积分的精确数学值为:{}\n".format(i, integrate(f(x,i),(x, 0,1)).evalf(2))) 

print("*************************************************************************\n")

N = 10**4
for j in range(1,9):
  n_tot = N
  n_below_curve = 0
  y_max = j # 函数最大值为D=j
  for i in range(N):
    x0=np.random.uniform(0,1)
    y0=np.random.uniform(0,y_max) # 调整y的采样范围到0到函数最大值
    if y0 <= f(x0,j): # 修正判断条件
      n_below_curve += 1
  ans = (n_below_curve / n_tot) * (1 * y_max) # 修正采样矩形面积计算
  print("D为{}时的积分结果为:{:.2f}\n".format(j, ans))

运行修正后的代码,输出结果会和精确值基本一致。


内容的提问来源于stack exchange,提问作者J.Snowden

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 05:21:01