> 0.1 + 0.2 == 0.3
false
Do you have
Need to go from
(e.g., 123e5)
to
0.10000000000000000555
0.2000000000000000111
0.29999999999999998889776975
Start with 32323232132321321111e124.
Lookup
Convert 32323232132321321111 to a float (not exact)
Compute
Approximation
You can always represent floats exactly (binary64) using at most 17 digits.
Never to this:
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
credit: xkcd
So we can express all positive floats as
12345678901234567E+/-123
.
Or
where mantissa
But
Tricks:
In ASCII/UTF-8, the digits 0, 1, ..., 9 have values
0x30, 0x31, ..., 0x39.
To recognize a digit:
bool is_made_of_eight_digits_fast(const char *chars) {
uint64_t val;
memcpy(&val, chars, 8);
return (((val & 0xF0F0F0F0F0F0F0F0) |
(((val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4))
== 0x3333333333333333);
}
(Works with ASCII, harder if input is UTF-16 as in Java/C#)
Using only three multiplications (instead of 7):
uint32_t parse_eight_digits_unrolled(const char *chars) {
uint64_t val;
memcpy(&val, chars, sizeof(uint64_t));
val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
return (val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32;
}
Noble Mushtak, Daniel Lemire, Fast Number Parsing Without Fallback Software: Practice and Experience 53 (7), 2023
credit: godbolt
Reading: Integer Division by Constants: Optimal Bounds, https://arxiv.org/abs/2012.12369
Need absolutely exact mantissa computation, to infinite precision.
But only happens for small decimal powers (
__uint128_t
._umul128
__umulh
bits.Mul64
Math.BigMul
__builtin_clzll
_BitScanReverse64
std::countl_zero
bits.LeadingZeros64
BitOperations.LeadingZeroCount
GNU GCC
LLVM clang
used by Apache Arrow, Yandex ClickHouse, Microsoft LightGBM
Algorithm adapted to Go's standard library (ParseFloat) by Nigel Tao and others
Release notes (version 1.16): ParseFloat (...) improving performance by up to a factor of 2.
Perfect rounding.
Blog post by Tao: The Eisel-Lemire ParseNumberF64 Algorithm
function | speed |
---|---|
from_str (standard) | 130 MB/s |
lexical (popular lib.) | 370 MB/s |
fast-float | 1200 MB/s |
rcppfastfloat: https://github.com/eddelbuettel/rcppfastfloat
3x faster than standard library
FastFloat.ParseDouble
is 5x faster than standard library (Double.Parse
)
https://github.com/CarlVerret/csFastFloat/
credit: Carl Verret, Egor Bogatov (Microsoft) and others

---
https://www.anandtech.com/show/21269/crucial-t705-gen5-nvme-ssd-a-145-gbps-consumer-flagship-with-2400-mts-232l-nand