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

基于蒙特卡洛模拟计算圆周率的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);

其他可优化的细节

  1. 变量声明规范:尽量用let/const替代var,避免变量提升带来的意外问题,比如把var Xpos改成const Xpos(因为每个循环里的坐标都是新值)。
  2. 无需取整操作:Math.floor(Math.random() * size)会把随机生成的浮点数坐标取整,丢失了边界附近的精度,直接用Math.random() * size得到的浮点数计算更准确。
  3. 性能优化:避免开根号: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++;
    }
    
  4. 输出方式:用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:04:30