Skip to content

Commit

Permalink
documentation for issue 261
Browse files Browse the repository at this point in the history
  • Loading branch information
lemire committed Aug 23, 2024
1 parent 3642e92 commit dab0827
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,39 @@ print the number 22250738585072012 three times:
std::cout << "parsed the number "<< i << std::endl;
```

## Behavior of result_out_of_range

When parsing floating-point values, the numbers can sometimes be too small (e.g., `1e-1000`) or
too large (e.g., `1e1000`). In such cases, it is customary to parse small values to zero and large
values to infinity. That is the behaviour followed by the fast_float library.

Specifically, we follow Jonathan Wakely's interpretation of the standard:

> 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()`.
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).

Hence, we have the following examples:

```cpp
double result = -1;
std::string str = "3e-1000";
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
// r.ec == std::errc::result_out_of_range
// r.ptr == str.data() + 7
// result == 0
```


```cpp
double result = -1;
std::string str = "3e1000";
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
// r.ec == std::errc::result_out_of_range
// r.ptr == str.data() + 6
// result == std::numeric_limits<double>::infinity()
```

## C++20: compile-time evaluation (constexpr)

In C++20, you may use `fast_float::from_chars` to parse strings
Expand Down
30 changes: 30 additions & 0 deletions tests/example_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,28 @@ consteval double parse(std::string_view input) {
constexpr double constexptest() { return parse("3.1415 input"); }
#endif

bool small() {
double result = -1;
std::string str = "3e-1000";
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
if(r.ec != std::errc::result_out_of_range) { return false; }
if(r.ptr != str.data() + 7) { return false; }
if(result != 0) { return false; }
printf("small values go to zero\n");
return true;
}

bool large() {
double result = -1;
std::string str = "3e1000";
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
if(r.ec != std::errc::result_out_of_range) { return false; }
if(r.ptr != str.data() + 6) { return false; }
if(result != std::numeric_limits<double>::infinity()) { return false; }
printf("large values go to infinity\n");
return true;
}

int main() {
const std::string input = "3.1416 xyz ";
double result;
Expand All @@ -87,6 +109,14 @@ int main() {
return EXIT_FAILURE;
}
std::cout << "parsed the number " << result << std::endl;
if (!small()) {
printf("Bug\n");
return EXIT_FAILURE;
}
if (!large()) {
printf("Bug\n");
return EXIT_FAILURE;
}

if (!many()) {
printf("Bug\n");
Expand Down

0 comments on commit dab0827

Please sign in to comment.