<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3081: Floating point from_chars API does not distinguish between overflow and underflow</title>
<meta property="og:title" content="Issue 3081: Floating point from_chars API does not distinguish between overflow and underflow">
<meta property="og:description" content="C++ library issue. Status: Open">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3081.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#Open">Open</a> status.</em></p>
<h3 id="3081"><a href="lwg-active.html#3081">3081</a>. Floating point <code>from_chars</code> API does not distinguish between overflow and underflow</h3>
<p><b>Section:</b> 28.2.3 <a href="https://wg21.link/charconv.from.chars">[charconv.from.chars]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a>
 <b>Submitter:</b> Greg Falcon <b>Opened:</b> 2018-03-12 <b>Last modified:</b> 2023-03-29</p>
<p><b>Priority: </b>2
</p>
<p><b>View other</b> <a href="lwg-index-open.html#charconv.from.chars">active issues</a> in [charconv.from.chars].</p>
<p><b>View all other</b> <a href="lwg-index.html#charconv.from.chars">issues</a> in [charconv.from.chars].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Open">Open</a> status.</p>
<p><b>Discussion:</b></p>
<p>
<code>strtod()</code> distinguishes between overflow and underflow by returning a value that is either 
very large or very small. Floating point <code>from_chars</code> does not currently offer any way for 
callers to distinguish these two cases.
<p/>
It would be beneficial if users could migrate from <code>strtod()</code> to <code>from_chars</code> without 
loss of functionality.
<p/>
I recommend that floating point <code>from_chars</code> use <code>value</code> as an overflow-vs-underflow 
reporting channel, in the same manner as <code>strtod()</code>.
<p/>
My proposed wording gives <code>from_chars</code> the same wide latitude that <code>strtod()</code> enjoys 
for handling underflow. A high-quality implementation would likely set <code>ec == result_out_of_range</code> 
for underflow only when the nearest representable <code>float</code> to the parsed value is a zero and 
the parsed mantissa was nonzero. In this case <code>value</code> would be set to (an appropriately-signed) zero. 
It is worth considering giving <code>from_chars</code> this more predictable behavior, if library writers 
feel they can provide this guarantee for all platforms. (I have a proof-of-concept integer-based 
implementation for IEEE doubles with this property.)
</p>

<p><i>[2018-06 Rapperswil Wednesday issues processing]</i></p>

<p>Marshall to provide updated wording and propose Tentatively Ready on the reflector.</p>
<p>Priority set to 2</p>

<p><i>[2018-08-23 Batavia Issues processing]</i></p>

<p>Status to Open; Marshall to reword</p>

<p><i>[2023-03-29; Jonathan adds further discussion]</i></p>

<p>
There are conflicting interpretations of "not in the range representable"
for floating-point types. One view is that 1e-10000 and 1e+10000 are outside
the representable range for a 64-bit double-precision <code>double</code>
(which has min/max exponents of -1022 and 1023). Another view is that the
representable range for floating-point types is [-inf,+inf], which means
that there are values that cannot be <em>accurately</em> represented,
but there are no values "not in the range representable". And 1e-10000 is
clearly within the range [0,<code>numeric_limits&lt;double&gt;::max()</code>],
even if we don't use infinity as the upper bound of the range.
Under the second interpretation, the result will be &pm;0.0 for underflow
and &pm;inf for overflow, but <code>ec</code> will not be set.
</p>
<p>
The current proposed resolution does address this, by making it clear
that <code>value</code> should be set to a very small or very large value
(with appropriate sign), but that <code>ec</code> should also be set.
The use of the word "overflow" for the integer overloads is a problem though,
because the result cannot "overflow" an unsigned integer type,
but can certainly be outside its range.
</p>



<p id="res-3081"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4727">N4727</a>.
</p>

<ol>
<li>
<p>Edit 28.2.3 <a href="https://wg21.link/charconv.from.chars">[charconv.from.chars]</a> as indicated:</p>
<blockquote>
<p>
[&hellip;] Otherwise, the characters matching the pattern are interpreted as a representation
of a value of the type of <code>value</code>. The member <code>ptr</code> of the return value points 
to the first character not matching the pattern, or has the value <code>last</code> if all characters 
match. If the parsed value is not in the range representable by the type of <code>value</code>, 
<del><code>value</code> is unmodified and</del> the member <code>ec</code> of the return value is equal
to <code>errc::result_out_of_range</code>. Otherwise, <code>value</code> is set to the parsed value, 
after rounding according to <code>round_to_nearest</code> (17.3.4 <a href="https://wg21.link/round.style">[round.style]</a>), and the member 
<code>ec</code> is value-initialized.
</p>
<pre>
from_chars_result from_chars(const char* first, const char* last,
                             <i>see below</i>&amp; value, int base = 10);
</pre>
<blockquote>
<p>
-2- <i>Requires:</i> <code>base</code> has a value between 2 and 36 (inclusive).
<p/>
-3- <i>Effects:</i> The pattern is the expected form of the subject sequence in the <code>"C"</code> 
locale for the given nonzero base, as described for <code>strtol</code>, except that no <code>"0x"</code> 
or <code>"0X"</code> prefix shall appear if the value of <code>base</code> is 16, and except that <code>'-'</code> is 
the only sign that may appear, and only if <code>value</code> has a signed type. <ins>On overflow, 
<code>value</code> is unmodified.</ins>
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
from_chars_result from_chars(const char* first, const char* last, float&amp; value,
                             chars_format fmt = chars_format::general);
from_chars_result from_chars(const char* first, const char* last, double&amp; value,
                             chars_format fmt = chars_format::general);
from_chars_result from_chars(const char* first, const char* last, long double&amp; value,
                             chars_format fmt = chars_format::general);
</pre>
<blockquote>
<p>
-6- <i>Requires:</i> <code>fmt</code> has the value of one of the enumerators of <code>chars_format</code>.
<p/>
-7- <i>Effects:</i> The pattern is the expected form of the subject sequence in the <code>"C"</code> 
locale, as described for <code>strtod</code>, except that
</p>
<ol style="list-style-type: none">
<li><p>(7.1) [&hellip;]</p></li>
<li><p>(7.2) [&hellip;]</p></li>
<li><p>(7.3) [&hellip;]</p></li>
<li><p>(7.4) [&hellip;]</p></li>
</ol>
<p>
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. <ins>On overflow, <code>value</code> is set to plus or minus 
<code>std::numeric_limits&lt;T&gt;::max()</code> of the appropriate type. On underflow, <code>value</code> 
is set to a value with magnitude no greater than <code>std::numeric_limits&lt;T&gt;::min()</code>.</ins>
<p/>
[&hellip;]
</p>
</blockquote>
</blockquote>
</li>
</ol>





</body>
</html>
