1
1
2
2
## fast_float number parsing library: 4x faster than strtod
3
3
4
- [ ![ Fuzzing Status] ( https://oss-fuzz-build-logs.storage.googleapis.com/badges/fast_float.svg )] ( https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:fast_float )
5
4
[ ![ Ubuntu 22.04 CI (GCC 11)] ( https://github.com/fastfloat/fast_float/actions/workflows/ubuntu22.yml/badge.svg )] ( https://github.com/fastfloat/fast_float/actions/workflows/ubuntu22.yml )
6
5
7
6
The fast_float library provides fast header-only implementations for the C++
@@ -16,22 +15,22 @@ floating-point numbers with a C++17-like syntax (the library itself only
16
15
requires C++11):
17
16
18
17
``` C++
19
- from_chars_result from_chars (const char * first, const char * last, float& value, ...);
20
- from_chars_result from_chars(const char * first, const char * last, double& value, ...);
18
+ from_chars_result from_chars (char const * first, char const * last, float & value, ...);
19
+ from_chars_result from_chars(char const * first, char const * last, double & value, ...);
21
20
```
22
21
23
22
You can also parse integer types:
24
23
25
24
```C++
26
- from_chars_result from_chars(const char* first, const char* last, int& value, ...);
27
- from_chars_result from_chars(const char* first, const char* last, unsigned& value, ...);
25
+ from_chars_result from_chars(char const * first, char const * last, int & value, ...);
26
+ from_chars_result from_chars(char const * first, char const * last, unsigned & value, ...);
28
27
```
29
28
30
29
The return type (` from_chars_result ` ) is defined as the struct:
31
30
32
31
``` C++
33
32
struct from_chars_result {
34
- const char * ptr;
33
+ char const * ptr;
35
34
std::errc ec;
36
35
};
37
36
```
@@ -60,7 +59,7 @@ Example:
60
59
#include <iostream>
61
60
62
61
int main() {
63
- const std::string input = "3.1416 xyz ";
62
+ std::string input = "3.1416 xyz ";
64
63
double result;
65
64
auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result);
66
65
if (answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
@@ -72,7 +71,7 @@ int main() {
72
71
You can parse delimited numbers:
73
72
74
73
``` C++
75
- const std::string input = " 234532.3426362,7869234.9823,324562.645" ;
74
+ std::string input = " 234532.3426362,7869234.9823,324562.645" ;
76
75
double result;
77
76
auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result);
78
77
if (answer.ec != std::errc()) {
@@ -108,9 +107,9 @@ The library seeks to follow the C++17 (see
108
107
[28.2.3.(6.1)](https://eel.is/c++draft/charconv.from.chars#6.1)) specification.
109
108
110
109
* The `from_chars` function does not skip leading white-space characters (unless
111
- `fast_float::chars_format::chars_format ` is set).
110
+ `fast_float::chars_format::skip_white_space ` is set).
112
111
* [A leading `+` sign](https://en.cppreference.com/w/cpp/utility/from_chars) is
113
- forbidden (unless `fast_float::chars_format::skip_white_space ` is set).
112
+ forbidden (unless `fast_float::chars_format::allow_leading_plus ` is set).
114
113
* It is generally impossible to represent a decimal value exactly as binary
115
114
floating-point number (`float` and `double` types). We seek the nearest value.
116
115
We round to an even mantissa when we are in-between two binary floating-point
@@ -119,8 +118,8 @@ The library seeks to follow the C++17 (see
119
118
Furthermore, we have the following restrictions:
120
119
121
120
* We support `float` and `double`, but not `long double`. We also support
122
- fixed-width floating-point types such as `std::float32_t` and
123
- `std::float64_t `.
121
+ fixed-width floating-point types such as `std::float64_t`, `std::float32_t`,
122
+ `std::float16_t`, and `std::bfloat16_t `.
124
123
* We only support the decimal format: we do not support hexadecimal strings.
125
124
* For values that are either very large or very small (e.g., `1e9999`), we
126
125
represent it using the infinity or negative infinity value and the returned
@@ -143,31 +142,31 @@ following code will print the number 22250738585072012 three times:
143
142
144
143
int main() {
145
144
uint64_t i;
146
- const char str[] = "22250738585072012";
147
- auto answer = fast_float::from_chars(str, str + strlen( str), i);
145
+ std::string str = "22250738585072012";
146
+ auto answer = fast_float::from_chars(str.data() , str.data() + str.size( ), i);
148
147
if (answer.ec != std::errc()) {
149
148
std::cerr << "parsing failure\n";
150
149
return EXIT_FAILURE;
151
150
}
152
- std::cout << "parsed the number "<< i << std::endl;
151
+ std::cout << "parsed the number " << i << std::endl;
153
152
154
- const char binstr[] = "1001111000011001110110111001001010110100111000110001100";
153
+ std::string binstr = "1001111000011001110110111001001010110100111000110001100";
155
154
156
- answer = fast_float::from_chars(binstr, binstr + strlen( binstr), i, 2);
155
+ answer = fast_float::from_chars(binstr.data() , binstr.data() + binstr.size( ), i, 2);
157
156
if (answer.ec != std::errc()) {
158
157
std::cerr << "parsing failure\n";
159
158
return EXIT_FAILURE;
160
159
}
161
- std::cout << "parsed the number "<< i << std::endl;
160
+ std::cout << "parsed the number " << i << std::endl;
162
161
163
- const char hexstr[] = "4f0cedc95a718c";
162
+ std::string hexstr = "4f0cedc95a718c";
164
163
165
- answer = fast_float::from_chars(hexstr, hexstr + strlen( hexstr), i, 16);
164
+ answer = fast_float::from_chars(hexstr.data() , hexstr.data() + hexstr.size( ), i, 16);
166
165
if (answer.ec != std::errc()) {
167
166
std::cerr << "parsing failure\n";
168
167
return EXIT_FAILURE;
169
168
}
170
- std::cout << "parsed the number "<< i << std::endl;
169
+ std::cout << "parsed the number " << i << std::endl;
171
170
return EXIT_SUCCESS;
172
171
}
173
172
```
@@ -242,7 +241,8 @@ constexpr double constexptest() {
242
241
## C++23: Fixed width floating-point types
243
242
244
243
The library also supports fixed-width floating-point types such as
245
- ` std::float32_t ` and ` std::float64_t ` . E.g., you can write:
244
+ ` std::float64_t ` , ` std::float32_t ` , ` std::float16_t ` , and ` std::bfloat16_t ` .
245
+ E.g., you can write:
246
246
247
247
``` C++
248
248
std::float32_t result;
@@ -259,7 +259,7 @@ following example:
259
259
#include < iostream>
260
260
261
261
int main () {
262
- const std::u16string input = u"3.1416 xyz ";
262
+ std::u16string input = u"3.1416 xyz ";
263
263
double result;
264
264
auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result);
265
265
if (answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
@@ -282,7 +282,7 @@ separator (e.g., the comma). You may use it as follows.
282
282
#include < iostream>
283
283
284
284
int main () {
285
- const std::string input = "3,1416 xyz ";
285
+ std::string input = "3,1416 xyz ";
286
286
double result;
287
287
fast_float::parse_options options{fast_float::chars_format::general, ','};
288
288
auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options);
@@ -299,9 +299,9 @@ int main() {
299
299
#include < iostream>
300
300
301
301
int main () {
302
- const std::string input = "1d+4";
302
+ std::string input = "1d+4";
303
303
double result;
304
- fast_float::parse_options options{ fast_float::chars_format::fortran };
304
+ fast_float::parse_options options{fast_float::chars_format::fortran};
305
305
auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options);
306
306
if ((answer.ec != std::errc()) || ((result != 10000))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
307
307
std::cout << "parsed the number " << result << std::endl;
@@ -316,9 +316,9 @@ int main() {
316
316
#include < iostream>
317
317
318
318
int main () {
319
- const std::string input = "+.1"; // not valid
319
+ std::string input = "+.1"; // not valid
320
320
double result;
321
- fast_float::parse_options options{ fast_float::chars_format::json };
321
+ fast_float::parse_options options{fast_float::chars_format::json};
322
322
auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options);
323
323
if (answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; }
324
324
return EXIT_SUCCESS;
@@ -332,9 +332,9 @@ By default the JSON format does not allow `inf`:
332
332
#include < iostream>
333
333
334
334
int main () {
335
- const std::string input = "inf"; // not valid in JSON
335
+ std::string input = "inf"; // not valid in JSON
336
336
double result;
337
- fast_float::parse_options options{ fast_float::chars_format::json };
337
+ fast_float::parse_options options{fast_float::chars_format::json};
338
338
auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options);
339
339
if (answer.ec == std::errc()) { std::cerr << "should have failed\n"; return EXIT_FAILURE; }
340
340
return EXIT_SUCCESS;
@@ -348,9 +348,9 @@ You can allow it with a non-standard `json_or_infnan` variant:
348
348
#include < iostream>
349
349
350
350
int main () {
351
- const std::string input = "inf"; // not valid in JSON but we allow it with json_or_infnan
351
+ std::string input = "inf"; // not valid in JSON but we allow it with json_or_infnan
352
352
double result;
353
- fast_float::parse_options options{ fast_float::chars_format::json_or_infnan };
353
+ fast_float::parse_options options{fast_float::chars_format::json_or_infnan};
354
354
auto answer = fast_float::from_chars_advanced(input.data(), input.data() + input.size(), result, options);
355
355
if (answer.ec != std::errc() || (!std::isinf(result))) { std::cerr << "should have parsed infinity\n"; return EXIT_FAILURE; }
356
356
return EXIT_SUCCESS;
@@ -367,7 +367,7 @@ The fast_float library is part of:
367
367
* [ WebKit] ( https://github.com/WebKit/WebKit ) , the engine behind Safari (Apple's
368
368
web browser),
369
369
* [ DuckDB] ( https://duckdb.org ) ,
370
- * [ Redis] ( https://github.com/redis/redis ) ,
370
+ * [ Redis] ( https://github.com/redis/redis ) and [ Valkey ] ( https://github.com/valkey-io/valkey ) ,
371
371
* [ Apache Arrow] ( https://github.com/apache/arrow/pull/8494 ) where it multiplied
372
372
the number parsing speed by two or three times,
373
373
* [ Google Jsonnet] ( https://github.com/google/jsonnet ) ,
@@ -429,8 +429,7 @@ abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfl
429
429
fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s
430
430
```
431
431
432
- See < https://github.com/lemire/simple_fastfloat_benchmark > for our benchmarking
433
- code.
432
+ See the [ Benchmarking] ( #benchmarking ) Section for instructions on how to run our benchmarks.
434
433
435
434
## Video
436
435
@@ -456,7 +455,7 @@ sufficiently recent version of CMake (3.11 or better at least):
456
455
FetchContent_Declare(
457
456
fast_float
458
457
GIT_REPOSITORY https://github.com/fastfloat/fast_float.git
459
- GIT_TAG tags/v6.1.6
458
+ GIT_TAG tags/v8.0.0
460
459
GIT_SHALLOW TRUE)
461
460
462
461
FetchContent_MakeAvailable(fast_float)
@@ -472,7 +471,7 @@ You may also use [CPM](https://github.com/cpm-cmake/CPM.cmake), like so:
472
471
CPMAddPackage(
473
472
NAME fast_float
474
473
GITHUB_REPOSITORY "fastfloat/fast_float"
475
- GIT_TAG v6.1.6 )
474
+ GIT_TAG v8.0.0 )
476
475
```
477
476
478
477
## Using as single header
@@ -484,7 +483,30 @@ if desired as described in the command line help.
484
483
485
484
You may directly download automatically generated single-header files:
486
485
487
- < https://github.com/fastfloat/fast_float/releases/download/v7.0.0/fast_float.h >
486
+ < https://github.com/fastfloat/fast_float/releases/download/v8.0.0/fast_float.h >
487
+
488
+ ## Benchmarking
489
+
490
+ The project has its own benchmarks with realistic data inputs. Under Linux or macOS,
491
+ you can use it as follows if your system supports C++17:
492
+
493
+ ```
494
+ cmake -B build -D FASTFLOAT_BENCHMARKS=ON
495
+ cmake --build build
496
+ ./build/benchmarks/realbenchmark
497
+ ```
498
+
499
+ Importantly, by default, the benchmark is built in Release mode.
500
+
501
+ The instructions are similar under Windows.
502
+
503
+ Under Linux and macOS, it is recommended to run the benchmarks in a privileged manner to get access
504
+ to hardware performance counters. You may be able to do so with the ` sudo ` command
505
+ in some cases:
506
+
507
+ ```
508
+ sudo ./build/benchmarks/realbenchmark
509
+ ```
488
510
489
511
## Packages
490
512
@@ -514,6 +536,8 @@ Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
514
536
href="LICENSE-BOOST">BOOST license</a >.
515
537
</sup >
516
538
539
+ <br />
540
+
517
541
<sub >
518
542
Unless you explicitly state otherwise, any contribution intentionally submitted
519
543
for inclusion in this repository by you, as defined in the Apache-2.0 license,
0 commit comments