以下是我为近似值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秒。救命啊!
答案 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元素的子字符串,这样就不必每次计算,结果将立即生效。