基于蒙特卡洛模拟计算圆周率的JavaScript脚本咨询
蒙特卡洛计算圆周率脚本分析与修正
嘿,我来帮你拆解这段计算圆周率的蒙特卡洛脚本,先把你的代码贴出来方便讨论:
const size = 500; const iterations = 10000000; let inside = 0; for (let i = 0; i < iterations; i++) { var Xpos = Math.floor(Math.random() * size); var Ypos = Math.floor(Math.random() * size); var dist = Math.hypot(Ypos-Xpos, size / 2 - size / 2); if (dist <= size / 2) { inside++; } } document.write(4 * inside / iterations);
核心问题:距离计算逻辑错误
这是脚本最关键的bug:你计算点到圆心的距离时写了Math.hypot(Ypos-Xpos, size / 2 - size / 2),第二个参数size/2 - size/2结果是0,这相当于只计算了Ypos - Xpos的绝对值,完全不是点(Xpos,Ypos)到圆心(size/2, size/2)的欧氏距离。
正确的距离计算应该是计算点与圆心在x、y方向上的差值,再求斜边:
const dist = Math.hypot(Xpos - size/2, Ypos - size/2);
其他可优化的细节
- 变量声明规范:尽量用
let/const替代var,避免变量提升带来的意外问题,比如把var Xpos改成const Xpos(因为每个循环里的坐标都是新值)。 - 无需取整操作:
Math.floor(Math.random() * size)会把随机生成的浮点数坐标取整,丢失了边界附近的精度,直接用Math.random() * size得到的浮点数计算更准确。 - 性能优化:避免开根号:
Math.hypot本质是计算平方根,我们可以通过比较平方值来跳过开根号步骤,大幅提升1亿次迭代的性能:const radius = size / 2; const radiusSquared = radius ** 2; // 循环内 const dx = x - radius; const dy = y - radius; if (dx**2 + dy**2 <= radiusSquared) { inside++; } - 输出方式:用
console.log替代document.write,避免直接覆盖页面内容,调试和查看结果更友好。
修正后的完整代码
const size = 500; const iterations = 100000000; // 按你的描述修正为1亿次迭代 let inside = 0; const radius = size / 2; const radiusSquared = radius ** 2; for (let i = 0; i < iterations; i++) { const x = Math.random() * size; const y = Math.random() * size; const dx = x - radius; const dy = y - radius; if (dx ** 2 + dy ** 2 <= radiusSquared) { inside++; } } console.log(`近似圆周率:${4 * inside / iterations}`);
原理回顾
蒙特卡洛计算π的逻辑是对的:在边长为size的正方形内随机生成点,落在四分之一圆内的点的比例乘以4就是π的近似值(因为正方形面积是size²,四分之一圆面积是π*(size/2)²/4,两者比值为π/4)。迭代次数越多,结果越接近真实的π值。
内容的提问来源于stack exchange,提问作者Schotsl
相关产品推荐
相关产品推荐

