Floating point 从Fortran格式解析浮点数 我正在为一个遗留的ASCII数据格式重写一个C++生锈解析器。此格式的实数值允许以任何Fortran认可的格式存储。不幸的是,Fortran可以识别一些Rust(或大多数其他语言)无法识别的格式。例如,值101.01可以表示为 101.01 1.0101E2 101.01e0 101.01D0 101.01d0 101.01+0 1010.1-1

Floating point 从Fortran格式解析浮点数 我正在为一个遗留的ASCII数据格式重写一个C++生锈解析器。此格式的实数值允许以任何Fortran认可的格式存储。不幸的是,Fortran可以识别一些Rust(或大多数其他语言)无法识别的格式。例如,值101.01可以表示为 101.01 1.0101E2 101.01e0 101.01D0 101.01d0 101.01+0 1010.1-1,floating-point,rust,Floating Point,Rust,前三种都是锈菌在本地识别的。剩下的四个是一个挑战。在C++中,我们使用以下例程解析这些值: double parse(const std::string& s){ char* p; const double significand = strtod(&s[0], &p); const long exponent = (*p == '\0') ? 0 : isalpha(*p) ?

前三种都是锈菌在本地识别的。剩下的四个是一个挑战。在C++中,我们使用以下例程解析这些值:

double parse(const std::string& s){
  char* p;
  const double significand = strtod(&s[0], &p);
  const long exponent = (*p == '\0') ? 
                          0 : isalpha(*p) ?
                            strtol(p+1, nullptr) :
                              strtol(p, nullptr);
  return significand * pow(10, exponent);
}

在查看Rust文档后,标准库似乎没有以
strtod
strtol
的方式提供部分字符串解析。我希望避免由于字符串的原因而多次使用字符串或使用正则表达式。

< P> C++中的示例没有给出精确的结果,但是RISE的浮点解析。

如果您手动实现近似解析,它可能比任何其他可用技术都快。我在本地做的一个快速测试表明,相对于标准库的
parse
方法的性能,您可以很容易地得到一个因子5


<>如果你希望有精确的解析,你的C++代码就不够了。预解析(例如使用Regex)可能是最简单的方法,但是您也可以从标准库中删除代码并进行修改。

这可能是对Veedrac答案的注释,但注释有点长

正如Veedrac解释的那样,精确解析浮动是非常困难的。标准库中的实现是完全准确的,并且经过了合理的优化。特别是,对于大多数使用naive算法的输入来说,它并不比naive算法慢多少。你应该用它。完整免责声明:我写的

我不同意Veedrac的地方是,如果您想重用代码,如何继续。从标准库中删除它是个坏主意。它非常庞大,大约有2.5k行代码,并且仍然会偶尔更改/改进,尽管很少,而且大部分都是以非常小的方式进行的。“但总有一天我会找到时间重写这条缓慢的道路,让它变得更好更快,”他承诺道如果删除此代码,则必须使用
core::num::dec2flt
模块并修改
parse
子模块以识别其他指数。当然,您不会自动从未来的改进中获益,如果您对性能感兴趣,这将是一种耻辱

最明智的方法是将其他格式转换为Rust支持的格式。如果它是
d
d
或裸
+
,您只需将其替换为
e
,并将其传递给字符串即可。只有在
1010.1-1
的情况下,才需要插入
e
并移动字符串的指数部分。这应该不会花费太多的性能。浮点字符串很短(最多20个左右字节,通常要少得多),实际的转换工作每字节要做大量的工作。对于C++代码来说也是如此,因为。或者至少它正在努力,它无法修复围绕它构建的特别算法。无论如何,它都在努力


另一种可能是使用FFI调用C的strtod。使用并调用
libc::strod
。这需要进行一些扭曲,才能将
&str
转换为指向
c_char
的原始指针,并且它将很难处理内部0字节,但您显示的代码无论如何都不是非常健壮。这将允许您以相同的性能、语义和(在)准确性将算法转换为Rust。

我感谢您的警告!我明白我发布的算法可能会引入错误;这就是说,我很幸运地处理了代表七位数精度被认为相当好的测量值的数据。在我们的测试过程中没有发现任何引入的错误。感谢您对github提交的参考。如果你只有7位数的精度并且需要速度,你只需要将值解析成一个
i64
并乘以缓存的10次方(通过将小数点添加到显式的一位来计算指数)就可以了。这应该是非常快的。我已经把这封信加入书签,以备将来参考。该应用程序旨在进行实时处理,但我们仍处于负载测试的早期阶段。如果发现文件解析是一个瓶颈,我将实现此方法进行比较。我们最终使用了您在这里的注释中描述的技术。再次感谢!我提到了翻译的想法,但没有强调它,因为阿普麦卡特尼明确表示它太慢了。我反对“它并不比天真不准确的算法慢多少”的说法;我刚刚快速创建了一个不准确的测试解析器,它的速度是“33.1453326”(和一些其他测试用例)的5倍。如果他担心这里的速度(假设他不只是为了速度而说),那就很难模棱两可了。在上面添加额外的解析只会加剧这种差异,性能调优也会加剧这种差异。目前,我已经实现了delnan建议的“最明智的方法”(但愿数据在未来几年会有所改善)。如果这种方法成本太高,我可能会实施您在回复评论中建议的策略Veedrac。@Veedrac来自我自己的基准测试,与标准库中的旧实现(几个月前)相比,我预计该类输入的速度大约为2倍。5x让我惊讶,你能把你的代码放在一个要点中,这样我就可以研究它吗?@delnan它不漂亮(每次我试图把它弄漂亮,结果都变慢了),但是。我不知道它有多正确,因为我几乎没有测试过它,但它似乎大部分都有效