近似Pi

时间:2013-03-03 19:58:14

标签: java eclipse decimal pi

以下是我为近似值103993/33102而编写的代码。用户输入精度。 这里k是用户输入的精度,asd是字符串形式的值

int tot = 4687;
int divisor = 33102;
StringBuffer fraction=new StringBuffer();
int tmp = tot;
    for(long i=1;i<=k;i++)
    {
        tmp = tmp*10;
        int res = tmp/divisor;
        fraction.append(res);
        tmp = tmp - res*divisor;
    }
    asd="3."+fraction.toString();

然而,当用户输入10 ^ 6的精度时,需要花费大量时间。时限为1秒。救命啊!

2 个答案:

答案 0 :(得分:2)

你的算法看起来很好。 StringBuffer是线程安全的,因此它很慢,因为它为每次调用append获取一个锁。使用StringBuilder,并使用您知道的所需容量构建它,即k。这可以防止数据的多个副本,因为StringBuilder内的缓冲区已扩展,以适应不断增长的字符串。

如果您阅读StringBuffer文档:

,这一点很清楚
  

从JDK 5发布版开始,这个类已经补充了一个设计用于单个线程StringBuilder的等效类。 StringBuilder类通常应优先于此使用,因为它支持所有相同的操作,但速度更快,因为它不执行同步。

由于您事先知道输出的确切大小,因此您还可以使用字节数组来保存数字。仍然最终转换为长度为10 ^ 6的字符串和输出是昂贵的。当我运行下面的代码时,创建字节数组只需0.016秒,转换为字符串只需0.06秒,打印时间超过1秒。要取得进步,您必须对如何在Java中进行快速i / o进行一些研究。如果您使用C语言或更接近硬件的其他语言,则正常的I / O例程可能足够快。

public void run() {
    int k = 1000000;
    long start = System.currentTimeMillis();
    int tot = 4687;
    int divisor = 33102;
    byte [] buf = new byte[k];
    int tmp = tot;
    for (int i = 0; i < k; i++) {
        tmp = tmp * 10;
        int res = tmp / divisor;
        buf[i] = (byte)(res + '0');
        tmp = tmp - res * divisor;
    }
    System.out.println((System.currentTimeMillis() - start) * .001);
    String s = new String(buf);
    System.out.println((System.currentTimeMillis() - start) * .001);
    System.out.print("3."); System.out.println(s);
    System.out.println((System.currentTimeMillis() - start) * .001);
}

答案 1 :(得分:0)

在一个非常大的字符串中预分配值,只需要创建一个K元素的子字符串,这样就不必每次计算,结果将立即生效。