Topic: Deprecating to_string() for floating point types and


Author: u97234@gmail.com
Date: Sun, 28 Feb 2016 05:06:29 -0800 (PST)
Raw View
------=_Part_106_111679161.1456664789405
Content-Type: multipart/alternative;
 boundary="----=_Part_107_2081630290.1456664789406"

------=_Part_107_2081630290.1456664789406
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

This post continues Deprecate to_string() for floating point types?=20
<https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-discus=
sion/6xhWgsEuvPo>

The original thread served it purpose and it seemed more appropriate to=20
start a new thread in this forum with a more proposal-like text for=20
evaluation.

------------------------

Summary
--------------

This document introduces the current behaviour of std::to_string() pointing=
=20
out it's fundamental problems with floating point types and suggests a=20
change to standard.

Introduction
-----------------

Converting numeric values to string is a common task in contexts like UI's=
=20
and human readable files and common enough to be listed as a newbie=20
question in C++ FAQ <https://isocpp.org/wiki/faq/newbie#int-to-string> [6].=
=20
Before C++11 there was no clear choice for conversion and some of the=20
options suggested [4]=20
<http://stackoverflow.com/questions/5290089/how-to-convert-a-number-to-stri=
ng-and-vice-versa-in-c>=20
[5]=20
<http://stackoverflow.com/questions/332111/how-do-i-convert-a-double-into-a=
-string-in-c>=20
for the task were:

   1. std::ostringstream
   2. sprintf
   3. boost::lexical_cast

These have problems ranging from complexity and performance to buffer=20
handling hazards and external dependency. With std::to_string() the general=
=20
answer got easy: use std::to_string().

This, however, is not a good answer for floating point types.

Floating point types are by their nature trickier to deal with and it's=20
harder to define what std::to_string() should do with floating point types.

The papers introducing std::to_string() [1]=20
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1803.html> [2]=20
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1982.html> [3]=20
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2408.html> does=
=20
not discuss the purpose of std::to_string() (i.e. what problem it is=20
intended to solve) and the current standard simply defines that return=20
string of std::to_string(double val) is identical to what sprintf(buf,=20
"%f", val) would generate with sufficient buffer size buf.

This paper argues that the decision is highly questionable, impractical and=
=20
a source of bugs thus suggesting a change to the standard.

Problem
------------

In form of examples, the definition of std::to_string(double val)=20
essentially as sprintf(buf, "%f", val) has the following implications:

   1. std::to_string(double(0)) =3D=3D "0.000000"
   2. std::to_string(double(10000)) =3D=3D "10000.000000"
   3. std::to_string(double(1e300)) =3D=3D=20
   "10000000000000000525047602552044202487044685811081591549158541155118024=
579889081957863713750804478640437044438328838781769425232353604305756447921=
847867069828483872009265758037378302337947880900593689532349707999450811190=
389676408800746527427801424945792587888200568428381156694721963868654594005=
40160.000000"
   4. std::to_string(double(1e-9)) =3D=3D "0.000000"

While it's not obvious how the conversion should work for floating point=20
types, it's hard to see that any acceptable implementation would have=20
behaviour as shown above. The problems are:

   - Redundant characters from information preservation point of view (1,=
=20
   2, 3, 4).
   - Unreadable output (3)
   - Failing to preserve even a single significant digit (4).

While redundant decimal characters may be even desired in some use cases,=
=20
the failure to preserve any significant digits is a serious issue=20
especially as it is not a rare corner case issue but affects a big=20
proportion of the whole double domain. How big a proportion? At least in=20
common implementations of double, base 10 exponent can get values in range=
=20
[-308, 308]. All values where exponent is in range [-308, -8] are converted=
=20
to "0.000000" by std::to_string(). And given that readability of values=20
with tens of digits is bad as demonstrated in example 3, the exponent range=
=20
where std::to_string() creates acceptable string representation is quite=20
small although the good range may well cover the most frequent use cases.

For comparison, here's a short survey of related implementations using=20
double (or similar type) value 1.23456789e-9:


   - Visual Basic (VS2015) ToString() : "1.23456789E-09"
   - C# (VS2015) ToString() : "1.23456789E-09"
   - Java toString() : "1.23456789E-9"
   - JavaScript toString() : "1.23456789e-9"
   - boost::lexical_cast<std::string>(1.23456789e-9):=20
   "1.2345678899999999e-09"
   - Qt 5.4 QString::number(1.23456789e-9) : "1.23457e-09"=20
   - Qt 5.4 QVariant(1.23456789e-9).toString() : "1.23456789e-09"
   - C++ to_string(1.23456789e-9) : "0.000000"


8 implementations, in 5 the result is precision-wise identical to value=20
written to source code, in 1 the result is non-lossy but longer than source=
=20
code version, in 1 the value is rounded to 6 significant digits and then=20
there's std::to_string() that simply wipes out all significant digits.

Ideal
-------

If std::to_string() for floating point types was created from scratch, the=
=20
question would be: what should it do? The following starting point is=20
assumed:


   - std::to_string() for integer types is defined and their=20
   implementations are what they currently are.
   - to_string() is required to print (human readable) decimal=20
   representation also of floating point values.


Some ideas:


   1. With integer types, the following condition is true: x !=3D y <=3D>=
=20
   to_string(x) !=3D to_string(y). Also for related from_string() implement=
ation=20
   such as stoul(), stoul(to_string(x)) =3D=3D x for all x of type T. In pl=
ain=20
   words this means that one can convert integer to string and read it back=
 to=20
   get exactly the same item from which the string representation was creat=
ed=20
   from. To keep the semantics the same for floating point types, require t=
he=20
   same property for floating point types.
   2. std::cout -like implementation that uses a standard defined default=
=20
   number of significant digits that is less than needed for non-lossy=20
   conversion.
   3. Use fixed decimal count.
   4. Print value as close to mathematically exact value as possible.

Option 4 would for example imply hugely long string representations as=20
demonstrated earlier so it's not viable option.

Option 3 is the current one and is obviously out of question.

In option 2 to_string() is allowed to create an approximation meaning that=
=20
to_string(x) =3D=3D to_string(y) for many different x and y thus changing t=
he=20
semantics compared to integer implementation. This is an essential=20
difference so there should be a very good reason for choosing this. The=20
argument is that there's none: prettiness and practicality arguments are=20
use case specific that can't be defined on standard level.

With this reasoning the only reasonable choice would be option 1. Notes on=
=20
it's implications:


   - The string representation is allowed to be ambiguous.
   - The string representation is not required to be mathematically exact:=
=20
   e.g. "1e300" is accepted because from_string(to_string(1e300)) =3D=3D=20
   from_string("1e300") even though mathematically double(1e300) !=3D 1e300=
..
   - Resulting string may be long but even in worst case is much shorter=20
   than what current to_string() prints for big values. For smaller values =
the=20
   resulting string may be shorter than with current to_string() because=20
   redundant decimals can be shortened (e.g. "1.0" vs "1.000000")

In this context the ideal could be formulated as follows:

to_string() with floating point types shall create such a string=20
representation that for related from_string() implementation such as=20
stod(), from_string(to_string(x)) =3D=3D x for all x in floating point type=
=20
domain. The string representation shall be portable across all=20
implementations that use the same floating point implementation in the=20
sense that reading the string in another implementation shall result to=20
value exactly the same as from which the string was created from. The=20
string representations are not, however, required to be identical on such=
=20
implementations, but is it recommended to be shortest possible using=20
similar scheme as defined in %g-family format in sprintf().

How to change the standard
----------------------------------------

Big complication is that to_string() can't be changed without introducing a=
=20
(breaking) change. The change could be of various type:


   1. Behaviour change on runtime: may break any existing code using the=20
   current definition.
   2. Compilation breaking or deprecation change: safer alternative=20
   implemented by API-change causing a compilation failure.
   3. Keep current behaviour but introduce parameters to make it possible=
=20
   to get a better behaviour.


Not particularly nice choices, but the runtime behaviour change can be=20
ruled out for starter leaving only two options. Breaking compilation or=20
deprecation is undesired, but preferred to having numerous programmers=20
making bugs due to this for decades to come. Thus the proposal is to=20
deprecate current to_string for floating point types and introduce a new=20
function with name to_string_f() or similar that behaves as described=20
earlier. to_string_f() shall also take optional parameters that allows=20
developer to fine tune the conversion like implemented e.g. in =20
QString::number() <http://doc.qt.io/qt-5/qstring.html#number-6> [7].=20
Options for fine tuning is important in the sense that making to_string_f()=
=20
too simple and restricted will too quickly cause programmer to resort to=20
old and lacking alternatives, although at this point the purpose of=20
to_string_f() is not to act as full featured sprintf-like formatting=20
implementation.

Early draft suggestion
-------------------------------

(float, long double and wstring omitted for clarity):

std::string to_string_f(double d, int precision =3D=20
special_value_requesting_shortest_nonlossy_representation, char format =3D=
=20
'g') noexcept;

Precision: Meaning depends on format-specifier as in sprintf in addition to=
=20
special items.
Format: Possible values: a, A, e, E, f, F, g, G as available for sprintf().

If precision or format is not within accepted range, to_string_f() returns=
=20
empty string.


Notes and open questions
--------------------------------------

-Usage examples and possible return values:
    to_string_f(1.0) -> "1.0"
    to_string_f(1.0, 10) -> "1.0"
    to_string_f(1.0, 2, 'f') -> "1.00"
    to_string_f(1.23456789e-9) -> "1.23456789e-9"
    to_string_f(1.23456789e-9, 2) -> "1.2e-9"
    to_string_f(1e300) -> "1e300"


-The essential question: is it feasible to implemented the=20
from_string(to_string(x)) =3D=3D x requirement given all the possible float=
ing=20
point implementations permitted by the C++ standard? If not, can the=20
condition be fulfilled by not requiring it for some corner cases such as=20
NaN's (e.g. having only single NaN instead of multiple)?

-Having int and char as parameters instead of string such as "%.3f" is=20
chosen for safety and simplicity: eliminates the need to do string parsing=
=20
and avoids possibility for errors in the users defined format string.

-Shortest necessary string representation can't be acquired using sprintf()=
=20
with maximal precision, but such implementation would be acceptable because=
=20
shortest possible string is not required. This is chosen to avoid the need=
=20
to define "shortest possible" which is not expected to have essential=20
relevance for the usage of to_string_f(). Also the implementation effort=20
from library implementers to guarantee the shortest possible on all=20
standard conforming C++ implementations might be unnecessarily high.

-For portability of string representation, see the end of section 'Ideal'

-Should the default value for precision be, say, -1 or an enum given the=20
conventions used for enums in std-namespace?=20

-Handling of out-of-range parameter values should be revised and defined.=
=20
The noexcept-property should however be preserved.

-How to handle locale: implicitly use the same as sprintf or require that=
=20
the output is locale independent? Locale-dependency would cause portability=
=20
issues so having locale-independent output would be desirable and in=20
accordance with the design intention as to_string_f() is not intended to do=
=20
full featured locale aware formatting.

-Would to_string_f() be appropriate name?


Details on examples
-----------------------------

Visual Basic (VS2015)
    Dim aDouble As Double
    aDouble =3D 0.00000000123456789
    Dim s As String =3D aDouble.ToString()
    Console.WriteLine(s)
   =20
C# (VS2015)
    double a =3D 1.23456789e-9;
    String s =3D a.ToString();
    Console.Write(s);
   =20
boost::lexical_cast (boost 1.55)
    auto s =3D boost::lexical_cast<std::string>(1.23456789e-9);
    std::cout << s;
   =20
Java (sun-jdk-8u51)
    Double a =3D 1.23456789e-9;
    String s =3D a.toString();
    System.out.println(s);
   =20
JavaScript (tested in Firefox 44)
    var dA =3D 1.23456789e-9;
    var sA =3D dA.toString();
   =20
Qt (5.4)
    QString s =3D QString::number(1.23456789e-9);
    auto s2 =3D QVariant(1.23456789e-9).toString();


References
----------

[1] N1803: Simple Numeric Access.=20
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1803.html
[2] N1982: Simple Numeric Access Revision 1.=20
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1982.html
[3] N2408: Simple Numeric Access Revision 2.=20
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2408.html
[4] How to convert a number to string and vice versa in C++.=20
http://stackoverflow.com/questions/5290089/how-to-convert-a-number-to-strin=
g-and-vice-versa-in-c
[5] How do I convert a double into a string in C++?.=20
http://stackoverflow.com/questions/332111/how-do-i-convert-a-double-into-a-=
string-in-c
[6] How do I convert an integer to a string?=20
https://isocpp.org/wiki/faq/newbie#int-to-string
[7] QString::number(). http://doc.qt.io/qt-5/qstring.html#number-6.
   =20

--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/7c6c597d-6d77-4675-8560-295c7feacc04%40isocpp.or=
g.

------=_Part_107_2081630290.1456664789406
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">This post continues=C2=A0<a href=3D"https://groups.google.=
com/a/isocpp.org/forum/?fromgroups#!topic/std-discussion/6xhWgsEuvPo">Depre=
cate to_string() for floating point types?</a><br><br>The original thread s=
erved it purpose and it seemed more appropriate to start a new thread in th=
is forum with a more proposal-like text for evaluation.<br><br>------------=
------------<br><br>Summary<br>--------------<br><br>This document introduc=
es the current behaviour of std::to_string() pointing out it&#39;s fundamen=
tal problems with floating point types and suggests a change to standard.<b=
r><br>Introduction<br>-----------------<br><br>Converting numeric values to=
 string is a common task in contexts like UI&#39;s and human readable files=
 and common enough to be listed as a newbie question in <a href=3D"https://=
isocpp.org/wiki/faq/newbie#int-to-string">C++ FAQ</a> [6]. Before C++11 the=
re was no clear choice for conversion and some of the options suggested=C2=
=A0<a href=3D"http://stackoverflow.com/questions/5290089/how-to-convert-a-n=
umber-to-string-and-vice-versa-in-c">[4]</a> <a href=3D"http://stackoverflo=
w.com/questions/332111/how-do-i-convert-a-double-into-a-string-in-c">[5]</a=
> for the task were:<br><ol><li>std::ostringstream</li><li>sprintf</li><li>=
boost::lexical_cast</li></ol>These have problems ranging from complexity an=
d performance to buffer handling hazards and external dependency. With std:=
:to_string() the general answer got easy: use std::to_string().<br><br>This=
, however, is not a good answer for floating point types.<br><br>Floating p=
oint types are by their nature trickier to deal with and it&#39;s harder to=
 define what std::to_string() should do with floating point types.<br><br>T=
he papers introducing std::to_string()=C2=A0<a href=3D"http://www.open-std.=
org/jtc1/sc22/wg21/docs/papers/2005/n1803.html">[1]</a>=C2=A0<a href=3D"htt=
p://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1982.html">[2]</a>=C2=
=A0<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2408=
..html">[3]</a> does not discuss the purpose of std::to_string() (i.e. what =
problem it is intended to solve) and the current standard simply defines th=
at return string of std::to_string(double val) is identical to what sprintf=
(buf, &quot;%f&quot;, val) would generate with sufficient buffer size buf.<=
br><br>This paper argues that the decision is highly questionable, impracti=
cal and a source of bugs thus suggesting a change to the standard.<br><br>P=
roblem<br>------------<br><br>In form of examples, the definition of std::t=
o_string(double val) essentially as sprintf(buf, &quot;%f&quot;, val) has t=
he following implications:<br><ol><li>std::to_string(double(0)) =3D=3D &quo=
t;0.000000&quot;</li><li>std::to_string(double(10000)) =3D=3D &quot;10000.0=
00000&quot;</li><li>std::to_string(double(1e300)) =3D=3D=20
&quot;100000000000000005250476025520442024870446858110815915491585411551180=
245798890819578637137508044786404370444383288387817694252323536043057564479=
218478670698284838720092657580373783023379478809005936895323497079994508111=
903896764088007465274278014249457925878882005684283811566947219638686545940=
0540160.000000&quot;</li><li>std::to_string(double(1e-9)) =3D=3D &quot;0.00=
0000&quot;</li></ol>While it&#39;s not obvious how the conversion should wo=
rk for floating point types, it&#39;s hard to see that any acceptable imple=
mentation would have behaviour as shown above. The problems are:<br><ul><li=
>Redundant characters from information preservation point of view (1, 2, 3,=
 4).</li><li>Unreadable output (3)</li><li>Failing to preserve even a singl=
e significant digit (4).</li></ul>While redundant decimal characters may be=
 even desired in some use cases, the failure to preserve any significant di=
gits is a serious issue especially as it is not a rare corner case issue bu=
t affects a big proportion of the whole double domain. How big a proportion=
? At least in common implementations of double, base 10 exponent can get va=
lues in range [-308, 308]. All values where exponent is in range [-308, -8]=
 are converted to &quot;0.000000&quot; by std::to_string(). And given that =
readability of values with tens of digits is bad as demonstrated in example=
 3, the exponent range where std::to_string() creates acceptable string rep=
resentation is quite small although the good range may well cover the most =
frequent use cases.<br><br>For comparison, here&#39;s a short survey of rel=
ated implementations using double (or similar type) value 1.23456789e-9:<br=
><br><ul><li>Visual Basic (VS2015) ToString() : &quot;1.23456789E-09&quot;<=
/li><li>C# (VS2015) ToString() : &quot;1.23456789E-09&quot;</li><li>Java to=
String() : &quot;1.23456789E-9&quot;</li><li>JavaScript toString() : &quot;=
1.23456789e-9&quot;</li><li>boost::lexical_cast&lt;std::string&gt;(1.234567=
89e-9): &quot;1.2345678899999999e-09&quot;</li><li>Qt 5.4 QString::number(1=
..23456789e-9) : &quot;1.23457e-09&quot; </li><li>Qt 5.4 QVariant(1.23456789=
e-9).toString() : &quot;1.23456789e-09&quot;</li><li>C++ to_string(1.234567=
89e-9) : &quot;0.000000&quot;</li></ul><br>8 implementations, in 5 the resu=
lt is precision-wise identical to value written to source code, in 1 the re=
sult is non-lossy but longer than source code version, in 1 the value is ro=
unded to 6 significant digits and then there&#39;s std::to_string() that si=
mply wipes out all significant digits.<br><br>Ideal<br>-------<br><br>If st=
d::to_string() for floating point types was created from scratch, the quest=
ion would be: what should it do? The following starting point is assumed:<b=
r><br><ul><li>std::to_string() for integer types is defined and their imple=
mentations are what they currently are.</li><li>to_string() is required to =
print (human readable) decimal representation also of floating point values=
..</li></ul><br>Some ideas:<br><br><ol><li>With integer types, the following=
 condition is true: x !=3D y &lt;=3D&gt;=20
to_string(x) !=3D to_string(y). Also for related from_string()=20
implementation such as stoul(), stoul(to_string(x)) =3D=3D x for all x of=
=20
type T. In plain words this means that one can convert integer to string
 and read it back to get exactly the same item from which the string=20
representation was created from. To keep the semantics the same for=20
floating point types, require the same property for floating point=20
types.</li><li>std::cout -like implementation that uses a standard defined =
default number of significant
 digits that=20
is less than needed for non-lossy conversion.</li><li>Use fixed decimal cou=
nt.</li><li>Print value as close to mathematically exact value as possible.=
</li></ol>Option 4 would for example imply hugely long string representatio=
ns as demonstrated earlier so it&#39;s not viable option.<br><br>Option 3 i=
s the current one and is obviously out of question.<br><br>In option 2 to_s=
tring() is allowed to create an approximation meaning that to_string(x) =3D=
=3D to_string(y) for many different x and y thus changing the semantics com=
pared to integer implementation. This is an essential difference so there s=
hould be a very good reason for choosing this. The argument is that there&#=
39;s none: prettiness and practicality arguments are use case specific that=
 can&#39;t be defined on standard level.<br><br>With this reasoning the onl=
y reasonable choice would be option 1. Notes on it&#39;s implications:<br><=
br><ul><li>The string representation is allowed to be ambiguous.</li><li>Th=
e string representation is not required to be mathematically exact:=20
e.g. &quot;1e300&quot; is accepted because from_string(to_string(1e300)) =
=3D=3D=20
from_string(&quot;1e300&quot;) even though mathematically double(1e300) !=
=3D 1e300.</li><li>Resulting string may be long but even in worst case is m=
uch shorter than
 what current to_string() prints for big values. For smaller values the=20
resulting string may be shorter than with current to_string() because=20
redundant decimals can be shortened (e.g. &quot;1.0&quot; vs &quot;1.000000=
&quot;)</li></ul>In this context the ideal could be formulated as follows:<=
br><br>to_string() with floating point types shall create such a string rep=
resentation that for related from_string() implementation such as stod(), f=
rom_string(to_string(x)) =3D=3D x for all x in floating point type domain. =
The string representation shall be portable across all implementations that=
 use the same floating point implementation in the sense that reading the s=
tring in another implementation shall result to value exactly the same as f=
rom which the string was created from. The string representations are not, =
however, required to be identical on such implementations, but is it recomm=
ended to be shortest possible using similar scheme as defined in %g-family =
format in sprintf().<br><br>How to change the standard<br>-----------------=
-----------------------<br><br>Big complication is that to_string() can&#39=
;t be changed without introducing a (breaking) change. The change could be =
of various type:<br><br><ol><li>Behaviour change on runtime: may break any =
existing code using the current definition.</li><li>Compilation breaking or=
 deprecation change: safer alternative implemented by API-change causing a =
compilation failure.</li><li>Keep current behaviour but introduce parameter=
s to make it possible to get a better behaviour.</li></ol><br>Not particula=
rly nice choices, but the runtime behaviour change can be ruled out for sta=
rter leaving only two options. Breaking compilation or deprecation is undes=
ired, but preferred to having numerous programmers making bugs due to this =
for decades to come. Thus the proposal is to deprecate current to_string fo=
r floating point types and introduce a new function with name to_string_f()=
 or similar that behaves as described earlier. to_string_f() shall also tak=
e optional parameters that allows developer to fine tune the conversion lik=
e implemented e.g. in=C2=A0 <a href=3D"http://doc.qt.io/qt-5/qstring.html#n=
umber-6">QString::number()</a> [7]. Options for fine tuning is important in=
 the sense that making to_string_f() too simple and restricted will too qui=
ckly cause programmer to resort to old and lacking alternatives, although a=
t this point the purpose of to_string_f() is not to act as full featured sp=
rintf-like formatting implementation.<br><br>Early draft suggestion<br>----=
---------------------------<br><br>(float, long double and wstring omitted =
for clarity):<br><br>std::string to_string_f(double d, int precision =3D sp=
ecial_value_requesting_shortest_nonlossy_representation, char format =3D &#=
39;g&#39;) noexcept;<br><br>Precision: Meaning depends on format-specifier =
as in sprintf in addition to special items.<br>Format: Possible values: a, =
A, e, E, f, F, g, G as available for sprintf().<br><br>If precision or form=
at is not within accepted range, to_string_f() returns empty string.<br><br=
><br>Notes and open questions<br>--------------------------------------<br>=
<br>-Usage examples and possible return values:<br>=C2=A0=C2=A0=C2=A0 to_st=
ring_f(1.0) -&gt; &quot;1.0&quot;<br>=C2=A0=C2=A0=C2=A0 to_string_f(1.0, 10=
) -&gt; &quot;1.0&quot;<br>=C2=A0=C2=A0=C2=A0 to_string_f(1.0, 2, &#39;f&#3=
9;) -&gt; &quot;1.00&quot;<br>=C2=A0=C2=A0=C2=A0 to_string_f(1.23456789e-9)=
 -&gt; &quot;1.23456789e-9&quot;<br>=C2=A0=C2=A0=C2=A0 to_string_f(1.234567=
89e-9, 2) -&gt; &quot;1.2e-9&quot;<br>=C2=A0=C2=A0=C2=A0 to_string_f(1e300)=
 -&gt; &quot;1e300&quot;<br><br><br>-The essential question: is it feasible=
 to implemented the from_string(to_string(x)) =3D=3D x requirement given al=
l the possible floating point implementations permitted by the C++ standard=
? If not, can the condition be fulfilled by not requiring it for some corne=
r cases such as NaN&#39;s (e.g. having only single NaN instead of multiple)=
?<br><br>-Having int and char as parameters instead of string such as &quot=
;%.3f&quot; is chosen for safety and simplicity: eliminates the need to do =
string parsing and avoids possibility for errors in the users defined forma=
t string.<br><br>-Shortest necessary string representation can&#39;t be acq=
uired using sprintf() with maximal precision, but such implementation would=
 be acceptable because shortest possible string is not required. This is ch=
osen to avoid the need to define &quot;shortest possible&quot; which is not=
 expected to have essential relevance for the usage of to_string_f(). Also =
the implementation effort from library implementers to guarantee the shorte=
st possible on all standard conforming C++ implementations might be unneces=
sarily high.<br><br>-For portability of string representation, see the end =
of section &#39;Ideal&#39;<br><br>-Should the default value for precision b=
e, say, -1 or an enum given the conventions used for enums in std-namespace=
? <br><br>-Handling of out-of-range parameter values should be revised and =
defined. The noexcept-property should however be preserved.<br><br>-How to =
handle locale: implicitly use the same as sprintf or require that the outpu=
t is locale independent? Locale-dependency would cause portability issues s=
o having locale-independent output would be desirable and in accordance wit=
h the design intention as to_string_f() is not intended to do full featured=
 locale aware formatting.<br><br>-Would to_string_f() be appropriate name?<=
br><br><br>Details on examples<br>-----------------------------<br><br>Visu=
al Basic (VS2015)<br>=C2=A0=C2=A0=C2=A0 Dim aDouble As Double<br>=C2=A0=C2=
=A0=C2=A0 aDouble =3D 0.00000000123456789<br>=C2=A0=C2=A0=C2=A0 Dim s As St=
ring =3D aDouble.ToString()<br>=C2=A0=C2=A0=C2=A0 Console.WriteLine(s)<br>=
=C2=A0=C2=A0=C2=A0 <br>C# (VS2015)<br>=C2=A0=C2=A0=C2=A0 double a =3D 1.234=
56789e-9;<br>=C2=A0=C2=A0=C2=A0 String s =3D a.ToString();<br>=C2=A0=C2=A0=
=C2=A0 Console.Write(s);<br>=C2=A0=C2=A0=C2=A0 <br>boost::lexical_cast (boo=
st 1.55)<br>=C2=A0=C2=A0=C2=A0 auto s =3D boost::lexical_cast&lt;std::strin=
g&gt;(1.23456789e-9);<br>=C2=A0=C2=A0=C2=A0 std::cout &lt;&lt; s;<br>=C2=A0=
=C2=A0=C2=A0 <br>Java (sun-jdk-8u51)<br>=C2=A0=C2=A0=C2=A0 Double a =3D 1.2=
3456789e-9;<br>=C2=A0=C2=A0=C2=A0 String s =3D a.toString();<br>=C2=A0=C2=
=A0=C2=A0 System.out.println(s);<br>=C2=A0=C2=A0=C2=A0 <br>JavaScript (test=
ed in Firefox 44)<br>=C2=A0=C2=A0=C2=A0 var dA =3D 1.23456789e-9;<br>=C2=A0=
=C2=A0=C2=A0 var sA =3D dA.toString();<br>=C2=A0=C2=A0=C2=A0 <br>Qt (5.4)<b=
r>=C2=A0=C2=A0=C2=A0 QString s =3D QString::number(1.23456789e-9);<br>=C2=
=A0=C2=A0=C2=A0 auto s2 =3D QVariant(1.23456789e-9).toString();<br><br><br>=
References<br>----------<br><br>[1] N1803: Simple Numeric Access. http://ww=
w.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1803.html<br>[2] N1982: Sim=
ple Numeric Access Revision 1. http://www.open-std.org/jtc1/sc22/wg21/docs/=
papers/2006/n1982.html<br>[3] N2408: Simple Numeric Access Revision 2. http=
://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2408.html<br>[4] How t=
o convert a number to string and vice versa in C++. http://stackoverflow.co=
m/questions/5290089/how-to-convert-a-number-to-string-and-vice-versa-in-c<b=
r>[5] How do I convert a double into a string in C++?. http://stackoverflow=
..com/questions/332111/how-do-i-convert-a-double-into-a-string-in-c<br>[6] H=
ow do I convert an integer to a string? https://isocpp.org/wiki/faq/newbie#=
int-to-string<br>[7] QString::number(). http://doc.qt.io/qt-5/qstring.html#=
number-6.<br>=C2=A0=C2=A0=C2=A0 <br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/7c6c597d-6d77-4675-8560-295c7feacc04%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/7c6c597d-6d77-4675-8560-295c7feacc04=
%40isocpp.org</a>.<br />

------=_Part_107_2081630290.1456664789406--
------=_Part_106_111679161.1456664789405--

.