2 个不稳定版本

0.2.0 2021 年 1 月 13 日
0.1.0 2021 年 1 月 10 日

#23解析工具

Download history 28353/week @ 2024-03-14 31168/week @ 2024-03-21 29185/week @ 2024-03-28 28818/week @ 2024-04-04 32010/week @ 2024-04-11 31737/week @ 2024-04-18 28161/week @ 2024-04-25 30245/week @ 2024-05-02 34876/week @ 2024-05-09 32577/week @ 2024-05-16 35624/week @ 2024-05-23 37051/week @ 2024-05-30 37960/week @ 2024-06-06 38616/week @ 2024-06-13 41807/week @ 2024-06-20 39919/week @ 2024-06-27

165,332 每月下载量
248 个 crate (29 直接) 中使用

MIT/Apache

85KB
2K SLoC

fast-float

Build Latest Version Documentation Apache 2.0 MIT Rustc 1.37+

此 crate 提供了一个从字符串到浮点数的超级快速十进制数解析器。

[dependencies]
fast-float = "0.2"

没有依赖项,可以通过禁用 "std" 功能在无 std 环境中使用此 crate。

编译器支持:rustc 1.37+。

使用方法

提供了两个顶级函数: parse()parse_partial(),两者都接受字符串或字节数组切片,并将输入解析为 f32f64

  • parse() 将整个字符串视为十进制数,如果字符串中有无效字符或字符串为空,则返回错误。
  • parse_partial() 尝试在给定的输入字符串的开始处找到最长的可以解析为十进制数的子字符串,在成功的情况下,返回解析值以及处理的字符数;如果字符串不以十进制数开头或为空,则返回错误。此函数在构建更复杂的解析器或解析数据流时非常有用。

示例

// Parse the entire string as a decimal number.
let s = "1.23e-02";
let x: f32 = fast_float::parse(s).unwrap();
assert_eq!(x, 0.0123);

// Parse as many characters as possible as a decimal number.
let s = "1.23e-02foo";
let (x, n) = fast_float::parse_partial::<f32, _>(s).unwrap();
assert_eq!(x, 0.0123);
assert_eq!(n, 8);
assert_eq!(&s[n..], "foo");

详细信息

此 crate 是 Daniel Lemire 的 fast_float C++ 库的直接移植(在移植过程中与 Daniel 的宝贵讨论帮助塑造了 crate 并使其达到现在的性能水平),并进行了一些针对 Rust 的调整。请参阅原始仓库以获取有关算法和实现的许多有用细节。

解析器是区域无关的。生成的值是最近的浮点值(使用f32f64),对于本应介于两个值之间的值,使用“四舍六入五留双”的约定。也就是说,我们提供符合IEEE标准的精确解析。

可以解析无穷大和NaN值,以及科学记数法。

支持小端和大端平台,并在小端架构上启用额外的优化。

测试

有几种方法对这个crate进行测试

  • 一套显式测试(来自原始库),覆盖了很多边缘情况。
  • 基于文件的测试套件(来自原始库;归功于Nigel Tao),约5M次测试。
  • 通过ryu格式化器将所有4B个float32数字完全往返。
  • 通过ryu格式化器往返大量随机float64数字。
  • 通过cargo-fuzz往返float64数字和模糊随机输入字符串。
  • 所有显式测试套件都在CI上运行;往返和模糊测试是手动运行的。

性能

所提供的解析器似乎在所有我们目前所知的C/C++/Rust浮点解析器中都有很大的优势,我们在所有测试过的数据集上测试了它 – 请见下文的详细基准测试(唯一的例外是原始的fast_float C++库 – 其性能与此crate的噪声界限相似)。在像Apple M1这样的现代机器上,解析吞吐量可以达到高达1.5 GB/s。

特别是,它比Rust标准库的FromStr::from_str()快2-8倍(对于较长的浮点字符串,因子更大),并且通常比最近的竞争对手快2-3倍。

有关算法的各种细节可以在原始C++库的存储库中找到,这里有一些简要的说明

  • 解析器针对最多19位有效数字的输入进行了优化,可以闪电般快速处理(这构成了所谓的“快速路径”)。我们相信大多数实际输入应该属于这一类别,我们将较长的输入视为“退化的”边缘情况,因为它不可避免地会导致溢出和精度损失。
  • 如果尾数超过19位,解析器将回退到“慢速路径”,在这种情况下,其性能大致与顶级Rust/C++库相当(尽管大多数时候仍然比它们快,但差距不大)。
  • 在小端系统上,对小数点后超过8位数的数字有额外的优化。

基准测试

以下是解析单个数字到64位浮点数的最佳时间(纳秒)表。

Intel i7-4771

Intel i7-4771 3.5GHz,macOS,Rust 1.49。

canada mesh uniform iidi iei rec32
fast-float 21.58 10.70 19.36 40.50 26.07 29.13
lexical 65.90 23.28 54.75 75.80 52.18 75.36
from_str 174.43 22.30 99.93 227.76 111.31 204.46
fast_float (C++) 22.78 10.99 20.05 41.12 27.51 30.85
abseil (C++) 42.66 32.88 46.01 50.83 46.33 49.95
netlib (C++) 57.53 24.86 64.72 56.63 36.20 67.29
strtod (C) 286.10 31.15 258.73 295.73 205.72 315.95

Apple M1

Apple M1,macOS,Rust 1.49。

canada mesh uniform iidi iei rec32
fast-float 14.84 5.98 11.24 33.24 21.30 17.86
lexical 47.09 16.51 43.46 56.06 36.68 55.48
from_str 136.00 13.84 74.64 179.87 77.91 154.53
fast_float (C++) 13.71 7.28 11.71 32.94 20.64 18.30
abseil (C++) 36.55 24.20 38.48 40.86 35.46 40.09
netlib (C++) 47.19 14.12 48.85 52.28 33.70 48.79
strtod (C) 176.13 21.48 165.43 187.98 132.19 190.63

AMD Rome

AMD Rome,Linux,Rust 1.49。

canada mesh uniform iidi iei rec32
fast-float 25.90 12.12 20.54 47.01 29.23 32.36
lexical 63.18 22.13 54.78 81.23 55.06 79.14
from_str 190.06 26.10 102.44 239.87 119.04 211.73
fast_float (C++) 21.29 10.47 18.31 42.33 24.56 29.76
abseil (C++) 44.54 34.13 47.38 52.64 43.77 53.03
netlib (C++) 69.43 23.31 79.98 72.17 35.81 86.91
strtod (C) 123.37 65.68 101.58 118.36 118.61 123.72

解析器

  • fast-float - 这个crate
  • lexicallexical_core,v0.7(无损;性能与有损相同)
  • from_str – Rust标准库,FromStr trait
  • fast_float (C++) – 'fast-float'方法的原始C++实现
  • abseil (C++) – Abseil C++ Common Libraries
  • netlib (C++) – C++ Network Library
  • strtod (C) – C标准库

数据集

  • canada – 存储在 canada.txt 文件中的数字
  • mesh – 存储在 mesh.txt 文件中的数字
  • uniform – 0到1之间的均匀随机数
  • iidi – 格式为 %d%d.%d 的随机数
  • iei – 格式为 %de%d 的随机数
  • rec32 – 随机32位整数的倒数

注意

  • 上述两个测试文件可以在这个仓库中找到。
  • 表中的Rust部分(以及一些其他基准测试)可以通过该仓库下extras/simple-bench中的基准测试工具生成。
  • 表中的C/C++部分(以及一些其他基准测试和解析器)可以通过该仓库中的C++实用工具生成。

许可证

根据您的选择,受Apache许可证,版本2.0MIT许可证的许可。
除非您明确声明,否则根据Apache-2.0许可证定义的,您有意提交以包含在此软件包中的任何贡献,都应如上所述双重许可,而不附加任何额外的条款或条件。

无运行时依赖