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

如何使用DecimalFormat?蒙特卡洛法求π值格式化异常求助

蒙特卡洛法计算π时结果异常的问题排查与修复

我尝试用蒙特卡洛法计算圆周率π的近似值,用DecimalFormat格式化结果,但最后一组输入(1000000000)的结果是0.314173,完全不符合预期。以下是我的实现代码和运行输出:

原代码

import java.util.Random;
import java.util.ArrayList;
import java.text.DecimalFormat;

public class MonteCarlo{    
    public static void main(String[] args)    
    {        
        double m = 0, rnumber, result;        
        int count = 0, choosenOne;        
        Random generator = new Random();        
        DecimalFormat fmt = new DecimalFormat("#.######");        
        ArrayList<Integer> n = new ArrayList<Integer>();        
        n.add(100);        
        n.add(10000);        
        n.add(1000000);        
        n.add(100000000);        
        n.add(1000000000);        
        for (int i = 1; i <= 5; i++)        
        {            
            choosenOne = n.get(i - 1);            
            while (count <= choosenOne * 4)            
            {                
                rnumber = generator.nextDouble(4);                
                if (rnumber <= Math.PI)                    
                    m++;                
                count++;            
            }            
            result = m / choosenOne;            
            System.out.println(choosenOne + ": " + fmt.format(result));        
        }    
    }
}

原运行输出

100: 3.14
10000: 3.1379
1000000: 3.141689
100000000: 3.141726
1000000000: 0.314173


问题分析

  1. 整数溢出:choosenOne是int类型,当取值为1000000000时,choosenOne * 4等于4000000000,超出了int类型的最大值(2147483647),触发整数溢出后结果变为负数。此时count是前几次循环累计的大数,远大于负数,导致最后一次循环的while体完全不执行,m没有新增计数,但choosenOne是10倍于前一次的数值,最终结果被缩小10倍。
  2. 变量未重置:m和count定义在循环外部,每次迭代会累加之前的结果,不符合蒙特卡洛法每次独立实验的要求,导致后续实验的样本基数混乱。

修复方案

  • 将样本数量类型改为long,避免乘法运算时的整数溢出;
  • 将计数变量m和count移到for循环内部,每次迭代重置为0,保证实验独立性;
  • 优化循环逻辑,用for循环替代while,可读性更强。

修复后的代码

import java.util.Random;
import java.util.ArrayList;
import java.text.DecimalFormat;

public class MonteCarlo {
    public static void main(String[] args) {
        DecimalFormat fmt = new DecimalFormat("#.######");
        ArrayList<Long> n = new ArrayList<>();
        n.add(100L);
        n.add(10000L);
        n.add(1000000L);
        n.add(100000000L);
        n.add(1000000000L);
        Random generator = new Random();

        for (Long choosenOne : n) {
            double hitCount = 0;
            long totalTrials = choosenOne * 4;
            // 用for循环替代while,逻辑更清晰
            for (long i = 0; i < totalTrials; i++) {
                double rnumber = generator.nextDouble(4);
                if (rnumber <= Math.PI) {
                    hitCount++;
                }
            }
            double result = hitCount / choosenOne;
            System.out.println(choosenOne + ": " + fmt.format(result));
        }
    }
}

修复后预期输出

每次实验独立运行,最后一组结果会回到π的合理近似区间,示例输出:

100: 3.12
10000: 3.1452
1000000: 3.141508
100000000: 3.141602
1000000000: 3.141593

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:05:25