> 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__umulhbits.Mul64Math.BigMul__builtin_clzll_BitScanReverse64std::countl_zerobits.LeadingZeros64BitOperations.LeadingZeroCountGNU 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