首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java中高效的strtod?

Java中高效的strtod?
EN

Stack Overflow用户
提问于 2011-09-07 10:45:54
回答 4查看 830关注 0票数 5

所以我有一个Java程序,我用它来处理几兆字节的数据。表现是一个值得关注的问题。

我分析了这个应用程序,所有内存分配的很大一部分以及CPU时间的很大一部分来自于执行一个简单的操作:

我有一系列的ASCII字符。我知道,从偏移量i到偏移量j的字符代表一个浮点数.我需要把那个浮点数提取到一个double中。

天真的Double.parseDouble(new String(buf, i, j - i))完成了这项工作。然而,这是花费大量时间和大量内存分配的地方,可能是因为:

  • new String()创建一个新对象,创建一个内部char[]数组并将字符复制到该数组中;
  • Double.parseDouble()创建一个FloatingDecimal对象,也创建一个char[]数组,并将字符复制到其中。

所有这些分配和所有这些复制并不是真正必要的。我能避开他们吗?

我真正想要的是一个strtod-like函数,它将接受char[] (或byte[])以及开始/结束偏移,并返回一个double

有什么建议吗?我应该推出自己的吗?我应该为strtod编写一个JNI包装器吗?我应该使用已经存在的Java库吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-09-07 11:06:43

我过去所做的是为ByteBuffer编写一个解析器(以避免字节到字符编码转换)加倍,反之亦然。如果您可以避免创建任何对象,它可能会更快。这种方法适用于内存映射文件,避免了一些复制成本。

核心代码如下所示。它不处理指数,但你可以把它加进去。

代码语言:javascript
复制
@Override
public double read() throws BufferUnderflowException {
  long value = 0;
  int exp = 0;
  boolean negative = false;
  int decimalPlaces = Integer.MIN_VALUE;
  while (true) {
    byte ch = buffer.get();
    if (ch >= '0' && ch <= '9') {
      while (value >= MAX_VALUE_DIVIDE_10) {
        value >>>= 1;
        exp++;
      }
      value = value * 10 + (ch - '0');
      decimalPlaces++;
    } else if (ch == '-') {
      negative = true;
    } else if (ch == '.') {
      decimalPlaces = 0;
    } else {
      break;
    }
  }

  return asDouble(value, exp, negative, decimalPlaces);
}

完整代码

一旦得到任何它不期望的字节,它就会停止,例如,,\n

票数 5
EN

Stack Overflow用户

发布于 2011-09-07 10:52:10

我会查看java.lang.Double的源代码,将执行parseDouble的代码复制到我自己的助手类中,并将其修改为直接在char[]上使用offsetlength

票数 5
EN

Stack Overflow用户

发布于 2011-09-07 12:14:48

出于好奇,我将strtod函数复制到Java中,与Double.parseDouble(String)方法相比,获得了10倍的加速比(即使没有在循环中创建新的String)。但也许这对你的实现来说还不够。

微观基准的制定表明:

Double.parseDouble():160万次转换/秒

Java strtod()方法: 10.5M转换/秒

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7332558

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档