Home

Awesome

fast-float

Build Latest Version Documentation Apache 2.0 MIT Rustc 1.37+

This crate provides a super-fast decimal number parser from strings into floats.

[dependencies]
fast-float = "0.2"

There are no dependencies and the crate can be used in a no_std context by disabling the "std" feature.

Compiler support: rustc 1.37+.

Usage

There's two top-level functions provided: parse() and parse_partial(), both taking either a string or a bytes slice and parsing the input into either f32 or f64:

Example:

// 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");

Details

This crate is a direct port of Daniel Lemire's fast_float C++ library (valuable discussions with Daniel while porting it helped shape the crate and get it to the performance level it's at now), with some Rust-specific tweaks. Please see the original repository for many useful details regarding the algorithm and the implementation.

The parser is locale-independent. The resulting value is the closest floating-point values (using either f32 or f64), using the "round to even" convention for values that would otherwise fall right in-between two values. That is, we provide exact parsing according to the IEEE standard.

Infinity and NaN values can be parsed, along with scientific notation.

Both little-endian and big-endian platforms are equally supported, with extra optimizations enabled on little-endian architectures.

Testing

There are a few ways this crate is tested:

Performance

The presented parser seems to beat all of the existing C/C++/Rust float parsers known to us at the moment by a large margin, in all of the datasets we tested it on so far – see detailed benchmarks below (the only exception being the original fast_float C++ library, of course – performance of which is within noise bounds of this crate). On modern machines like Apple M1, parsing throughput can reach up to 1.5 GB/s.

In particular, it is faster than Rust standard library's FromStr::from_str() by a factor of 2-8x (larger factor for longer float strings), and is typically 2-3x faster than the nearest competitors.

While various details regarding the algorithm can be found in the repository for the original C++ library, here are few brief notes:

Benchmarks

Below are tables of best timings in nanoseconds for parsing a single number into a 64-bit float.

Intel i7-4771

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

canadameshuniformiidiieirec32
fast-float21.5810.7019.3640.5026.0729.13
lexical65.9023.2854.7575.8052.1875.36
from_str174.4322.3099.93227.76111.31204.46
fast_float (C++)22.7810.9920.0541.1227.5130.85
abseil (C++)42.6632.8846.0150.8346.3349.95
netlib (C)57.5324.8664.7256.6336.2067.29
strtod (C)286.1031.15258.73295.73205.72315.95

Apple M1

Apple M1, macOS, Rust 1.49.

canadameshuniformiidiieirec32
fast-float14.845.9811.2433.2421.3017.86
lexical47.0916.5143.4656.0636.6855.48
from_str136.0013.8474.64179.8777.91154.53
fast_float (C++)13.717.2811.7132.9420.6418.30
abseil (C++)36.5524.2038.4840.8635.4640.09
netlib (C)47.1914.1248.8552.2833.7048.79
strtod (C)176.1321.48165.43187.98132.19190.63

AMD Rome

AMD Rome, Linux, Rust 1.49.

canadameshuniformiidiieirec32
fast-float25.9012.1220.5447.0129.2332.36
lexical63.1822.1354.7881.2355.0679.14
from_str190.0626.10102.44239.87119.04211.73
fast_float (C++)21.2910.4718.3142.3324.5629.76
abseil (C++)44.5434.1347.3852.6443.7753.03
netlib (C)69.4323.3179.9872.1735.8186.91
strtod (C)123.3765.68101.58118.36118.61123.72

Parsers

Datasets

Notes

<br>

References

License

<sup> Licensed under either of <a href="LICENSE-APACHE">Apache License, Version 2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option. </sup> <br> <sub> Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. </sub>