Skip to content

Commit d797a3a

Browse files
committed
Adding example.
1 parent cfb44c2 commit d797a3a

File tree

3 files changed

+100
-24
lines changed

3 files changed

+100
-24
lines changed

README.md

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ struct from_chars_result {
2121
```
2222

2323
It parses the character sequence [first,last) for a number. It parses floating-point numbers expecting
24-
a locale-independent format equivalent to the C++17 from_chars function.
25-
The resulting floating-point value is the closest floating-point values (using either float or double),
24+
a locale-independent format equivalent to the C++17 from_chars function.
25+
The resulting floating-point value is the closest floating-point values (using either float or double),
2626
using the "round to even" convention for values that would otherwise fall right in-between two values.
2727
That is, we provide exact parsing according to the IEEE standard.
2828

@@ -40,7 +40,7 @@ Example:
4040
``` C++
4141
#include "fast_float/fast_float.h"
4242
#include <iostream>
43-
43+
4444
int main() {
4545
const std::string input = "3.1416 xyz ";
4646
double result;
@@ -53,15 +53,15 @@ int main() {
5353

5454

5555
Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of
56-
the type `fast_float::chars_format`. It is a bitset value: we check whether
56+
the type `fast_float::chars_format`. It is a bitset value: we check whether
5757
`fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set
5858
to determine whether we allow the fixed point and scientific notation respectively.
5959
The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`.
6060

61-
The library seeks to follow the C++17 (see [20.19.3](http://eel.is/c++draft/charconv.from.chars).(7.1)) specification.
61+
The library seeks to follow the C++17 (see [20.19.3](http://eel.is/c++draft/charconv.from.chars).(7.1)) specification.
6262
* The `from_chars` function does not skip leading white-space characters.
6363
* [A leading `+` sign](https://en.cppreference.com/w/cpp/utility/from_chars) is forbidden.
64-
* It is generally impossible to represent a decimal value exactly as binary floating-point number (`float` and `double` types). We seek the nearest value. We round to an even mantissa when we are in-between two binary floating-point numbers.
64+
* It is generally impossible to represent a decimal value exactly as binary floating-point number (`float` and `double` types). We seek the nearest value. We round to an even mantissa when we are in-between two binary floating-point numbers.
6565

6666
Furthermore, we have the following restrictions:
6767
* We only support `float` and `double` types at this time.
@@ -76,16 +76,16 @@ We support Visual Studio, macOS, Linux, freeBSD. We support big and little endia
7676

7777

7878
The C++ standard stipulate that `from_chars` has to be locale-independent. In
79-
particular, the decimal separator has to be the period (`.`). However,
80-
some users still want to use the `fast_float` library with in a locale-dependent
79+
particular, the decimal separator has to be the period (`.`). However,
80+
some users still want to use the `fast_float` library with in a locale-dependent
8181
manner. Using a separate function called `from_chars_advanced`, we allow the users
82-
to pass a `parse_options` instance which contains a custom decimal separator (e.g.,
82+
to pass a `parse_options` instance which contains a custom decimal separator (e.g.,
8383
the comma). You may use it as follows.
8484

8585
```C++
8686
#include "fast_float/fast_float.h"
8787
#include <iostream>
88-
88+
8989
int main() {
9090
const std::string input = "3,1416 xyz ";
9191
double result;
@@ -97,6 +97,32 @@ int main() {
9797
}
9898
```
9999

100+
You can parse delimited numbers:
101+
```C++
102+
const std::string input = "234532.3426362,7869234.9823,324562.645";
103+
double result;
104+
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
105+
if(answer.ec != std::errc()) {
106+
// check error
107+
}
108+
// we have result == 234532.3426362.
109+
if(answer.ptr[0] != ',') {
110+
// unexpected delimiter
111+
}
112+
answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
113+
if(answer.ec != std::errc()) {
114+
// check error
115+
}
116+
// we have result == 7869234.9823.
117+
if(answer.ptr[0] != ',') {
118+
// unexpected delimiter
119+
}
120+
answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
121+
if(answer.ec != std::errc()) {
122+
// check error
123+
}
124+
// we have result == 324562.645.
125+
```
100126
101127
## Reference
102128
@@ -114,7 +140,7 @@ int main() {
114140
115141
The fast_float library is part of GCC (as of version 12): the `from_chars` function in GCC relies on fast_float.
116142
117-
The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba).
143+
The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba).
118144
119145
The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM).
120146
@@ -132,14 +158,14 @@ It can parse random floating-point numbers at a speed of 1 GB/s on some systems.
132158
<img src="http://lemire.me/blog/wp-content/uploads/2020/11/fastfloat_speed.png" width="400">
133159
134160
```
135-
$ ./build/benchmarks/benchmark
161+
$ ./build/benchmarks/benchmark
136162
# parsing random integers in the range [0,1)
137-
volume = 2.09808 MB
138-
netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s
139-
doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s
140-
strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s
141-
abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s
142-
fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s
163+
volume = 2.09808 MB
164+
netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s
165+
doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s
166+
strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s
167+
abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s
168+
fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s
143169
```
144170
145171
See https://github.com/lemire/simple_fastfloat_benchmark for our benchmarking code.
@@ -180,9 +206,9 @@ You should change the `GIT_TAG` line so that you recover the version you wish to
180206

181207
## Using as single header
182208

183-
The script `script/amalgamate.py` may be used to generate a single header
209+
The script `script/amalgamate.py` may be used to generate a single header
184210
version of the library if so desired.
185-
Just run the script from the root directory of this repository.
211+
Just run the script from the root directory of this repository.
186212
You can customize the license type and output file if desired as described in
187213
the command line help.
188214

@@ -192,11 +218,11 @@ https://github.com/fastfloat/fast_float/releases/download/v3.4.0/fast_float.h
192218

193219
## Credit
194220

195-
Though this work is inspired by many different people, this work benefited especially from exchanges with
196-
Michael Eisel, who motivated the original research with his key insights, and with Nigel Tao who provided
221+
Though this work is inspired by many different people, this work benefited especially from exchanges with
222+
Michael Eisel, who motivated the original research with his key insights, and with Nigel Tao who provided
197223
invaluable feedback. Rémy Oudompheng first implemented a fast path we use in the case of long digits.
198224

199-
The library includes code adapted from Google Wuffs (written by Nigel Tao) which was originally published
225+
The library includes code adapted from Google Wuffs (written by Nigel Tao) which was originally published
200226
under the Apache 2.0 license.
201227

202228
## License

tests/basictest.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,33 @@ TEST_CASE("decimal_point_parsing") {
224224
}
225225
}
226226

227+
TEST_CASE("issue19") {
228+
const std::string input = "234532.3426362,7869234.9823,324562.645";
229+
double result;
230+
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
231+
CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse up to 234532.3426362\n");
232+
CHECK_MESSAGE(answer.ptr == input.data() + 14,
233+
"Parsed the number " << result
234+
<< " and stopped at the wrong character: after " << (answer.ptr - input.data()) << " characters");
235+
CHECK_MESSAGE(result == 234532.3426362, "We want to parse234532.3426362\n");
236+
CHECK_MESSAGE(answer.ptr[0] == ',', "We want to parse up to the comma\n");
237+
238+
answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
239+
CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse 7869234.9823\n");
240+
CHECK_MESSAGE(answer.ptr == input.data() + 27,
241+
"Parsed the number " << result
242+
<< " and stopped at the wrong character " << (answer.ptr - input.data()));
243+
CHECK_MESSAGE(answer.ptr[0] == ',', "We want to parse up to the comma\n");
244+
CHECK_MESSAGE(result == 7869234.9823, "We want to parse up 7869234.9823\n");
245+
246+
answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
247+
CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse 324562.645\n");
248+
CHECK_MESSAGE(answer.ptr == input.data() + 38,
249+
"Parsed the number " << result
250+
<< " and stopped at the wrong character " << (answer.ptr - input.data()));
251+
CHECK_MESSAGE(result == 324562.645, "We want to parse up 7869234.9823\n");
252+
}
253+
227254
TEST_CASE("issue19") {
228255
const std::string input = "3.14e";
229256
double result;

tests/example_test.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,35 @@
33
#include <iostream>
44
#include <string>
55
#include <system_error>
6-
6+
7+
8+
bool many() {
9+
const std::string input = "234532.3426362,7869234.9823,324562.645";
10+
double result;
11+
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
12+
if(answer.ec != std::errc()) { return false; }
13+
if(result != 234532.3426362) { return false; }
14+
if(answer.ptr[0] != ',') { return false; }
15+
answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
16+
if(answer.ec != std::errc()) { return false; }
17+
if(result != 7869234.9823) { return false; }
18+
if(answer.ptr[0] != ',') { return false; }
19+
answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
20+
if(answer.ec != std::errc()) { return false; }
21+
if(result != 324562.645) { return false; }
22+
return true;
23+
}
24+
725
int main() {
826
const std::string input = "3.1416 xyz ";
927
double result;
1028
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
1129
if((answer.ec != std::errc()) || ((result != 3.1416))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
1230
std::cout << "parsed the number " << result << std::endl;
31+
32+
if(!many()) {
33+
printf("Bug\n");
34+
return EXIT_FAILURE;
35+
}
1336
return EXIT_SUCCESS;
1437
}

0 commit comments

Comments
 (0)