Skip to content

Commit 00f2593

Browse files
authored
Merge pull request #263 from fastfloat/doc_issue_261
documentation for issue 261
2 parents 3642e92 + dab0827 commit 00f2593

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,39 @@ print the number 22250738585072012 three times:
144144
std::cout << "parsed the number "<< i << std::endl;
145145
```
146146

147+
## Behavior of result_out_of_range
148+
149+
When parsing floating-point values, the numbers can sometimes be too small (e.g., `1e-1000`) or
150+
too large (e.g., `1e1000`). In such cases, it is customary to parse small values to zero and large
151+
values to infinity. That is the behaviour followed by the fast_float library.
152+
153+
Specifically, we follow Jonathan Wakely's interpretation of the standard:
154+
155+
> In any case, the resulting value is one of at most two floating-point values closest to the value of the string matching the pattern. On overflow, value is set to plus or minus `std::numeric_limits<T>::max()` of the appropriate type. On underflow, value is set to a value with magnitude no greater than `std::numeric_limits<T>::min()`.
156+
157+
It is also the approach taken by the [Microsoft C++ library](https://github.com/microsoft/STL/blob/62205ab155d093e71dd9588a78f02c5396c3c14b/tests/std/tests/P0067R5_charconv/test.cpp#L943-L946).
158+
159+
Hence, we have the following examples:
160+
161+
```cpp
162+
double result = -1;
163+
std::string str = "3e-1000";
164+
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
165+
// r.ec == std::errc::result_out_of_range
166+
// r.ptr == str.data() + 7
167+
// result == 0
168+
```
169+
170+
171+
```cpp
172+
double result = -1;
173+
std::string str = "3e1000";
174+
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
175+
// r.ec == std::errc::result_out_of_range
176+
// r.ptr == str.data() + 6
177+
// result == std::numeric_limits<double>::infinity()
178+
```
179+
147180
## C++20: compile-time evaluation (constexpr)
148181

149182
In C++20, you may use `fast_float::from_chars` to parse strings

tests/example_test.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,28 @@ consteval double parse(std::string_view input) {
7777
constexpr double constexptest() { return parse("3.1415 input"); }
7878
#endif
7979

80+
bool small() {
81+
double result = -1;
82+
std::string str = "3e-1000";
83+
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
84+
if(r.ec != std::errc::result_out_of_range) { return false; }
85+
if(r.ptr != str.data() + 7) { return false; }
86+
if(result != 0) { return false; }
87+
printf("small values go to zero\n");
88+
return true;
89+
}
90+
91+
bool large() {
92+
double result = -1;
93+
std::string str = "3e1000";
94+
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
95+
if(r.ec != std::errc::result_out_of_range) { return false; }
96+
if(r.ptr != str.data() + 6) { return false; }
97+
if(result != std::numeric_limits<double>::infinity()) { return false; }
98+
printf("large values go to infinity\n");
99+
return true;
100+
}
101+
80102
int main() {
81103
const std::string input = "3.1416 xyz ";
82104
double result;
@@ -87,6 +109,14 @@ int main() {
87109
return EXIT_FAILURE;
88110
}
89111
std::cout << "parsed the number " << result << std::endl;
112+
if (!small()) {
113+
printf("Bug\n");
114+
return EXIT_FAILURE;
115+
}
116+
if (!large()) {
117+
printf("Bug\n");
118+
return EXIT_FAILURE;
119+
}
90120

91121
if (!many()) {
92122
printf("Bug\n");

0 commit comments

Comments
 (0)