如何使用Numba实现蒙特卡洛法π值近似模拟并校验代码正确性
蒙特卡洛估算π的Numba代码问题修正
你的现有代码设置存在逻辑错误,是导致结果偏差的核心原因,具体问题如下:
return语句缩进错误:当前返回值逻辑写在循环内部的点判断分支中,只要第一个点落在圆内就会直接终止循环返回结果,完全没有跑完预设的所有采样点,结果完全不具备统计意义。- 随机数接口不兼容Numba nopython模式:Python标准库的
random()无法在Numba的nopython编译模式下稳定运行,会出现随机数生成异常甚至直接报错,需要替换为Numba兼容的numpy.random接口。 - 计算逻辑位置错误:pi的估算值不需要每命中一个点就计算一次,应该等所有采样点全部统计完圆内点总数后,再统一通过
4*圆内点数/总点数计算最终估算值。另外你传入函数的真实math.pi参数没有参与任何计算逻辑,属于冗余设计。 - 额外性能优化点:判断点是否在圆内时,不需要对
x*x+y*y做开平方运算,直接和1比较大小即可,和开平方后的判断结果完全一致,能减少不必要的计算开销。
修正后可直接运行的代码
import numba import numpy as np import math @numba.jit(nopython=True) def estimate_pi(sample_num): inside_count = 0 for _ in range(sample_num): x = np.random.random() y = np.random.random() if x*x + y*y <= 1: inside_count += 1 return 4 * inside_count / sample_num # 测试不同规模的采样点 for n in [10, 100, 1000, 10000, 100000, 1000000]: pi_est = estimate_pi(n) print(f"采样点数{n:>7d} | 估算π值: {pi_est:.6f} | 与真实值偏差: {abs(pi_est - math.pi):.6f}")
补充说明:你提到的10和
10**1是完全相同的采样规模,测试梯度可以设置为10的1次到7次幂的序列。蒙特卡洛方法的估算精度随采样点数提升而提高,采样量为10的时候结果波动极大(取值范围在2.04.0之间都属于正常情况),当采样量达到1e6级别时,通常可以稳定到小数点后23位的精度。Numba JIT模式第一次运行函数时会有短暂编译耗时,后续重复调用的运行速度会比纯Python实现高1~2个数量级。
内容的提问来源于stack exchange,提问作者12666727b9
相关产品推荐
相关产品推荐

