220 24831 <89c4ad80-fd43-4c00-87fd-8dc38ba50739@isocpp.org> article
Path: news.gmane.org!not-for-mail
From: d.h.gottwald@gmail.com
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Deprecating to_string() for floating point types
 and introducing a replacement
Date: Mon, 29 Feb 2016 07:47:51 -0800 (PST)
Lines: 766
Approved: news@gmane.org
Message-ID: <89c4ad80-fd43-4c00-87fd-8dc38ba50739@isocpp.org>
References: <7c6c597d-6d77-4675-8560-295c7feacc04@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_179_173916395.1456760871783"
X-Trace: ger.gmane.org 1456760888 22033 80.91.229.3 (29 Feb 2016 15:48:08 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Mon, 29 Feb 2016 15:48:08 +0000 (UTC)
Cc: u97234@gmail.com
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBDZ27EHJ34JRBKGQ2G3AKGQEABYWNTY@isocpp.org Mon Feb 29 16:47:58 2016
Return-path: <std-proposals+bncBDZ27EHJ34JRBKGQ2G3AKGQEABYWNTY@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-vk0-f72.google.com ([209.85.213.72])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBDZ27EHJ34JRBKGQ2G3AKGQEABYWNTY@isocpp.org>)
	id 1aaQ3A-0003LT-3Z
	for gclcip-std-proposals@m.gmane.org; Mon, 29 Feb 2016 16:47:56 +0100
Original-Received: by mail-vk0-f72.google.com with SMTP id e6sf252321442vkh.0
        for <gclcip-std-proposals@m.gmane.org>; Mon, 29 Feb 2016 07:47:55 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:cc:message-id:in-reply-to:references:subject
         :mime-version:x-original-sender:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=XczULBTlbSR/r+YGjiGbf/2AArM0f2wIL9i3S1VFoJw=;
        b=x+TeoALiWtWNAbaoB0ywfg5KD4VsxxahyXk/m1hfOwMbpg0m4ufzZkUpx2hUmo1Hfh
         ephpWdGyqhKuOz1rhxLt3Un01Xcmo37B/XCUxuPzKdATwUTIvgi8Q8cK4lgfgpO3wTxu
         qAj6q2LXOIM/clhFrWMw5U/KSOttV6/1ROlDQi/AJzBNltgt2jyPF2HXGZGLS2XQj4sF
         Lovimtzk6A+5VEJHE+XPqDp1nc9yk4XRBZSf2M4L2Rz9BYoC5mABsSZ8CGX4UddtMpCf
         ZogtVy8qMZco7ladt/eTnLMOJn8cjQxKd88/RW6v38l0p99j9IMpw60ZE0kXdC20KU+z
         xeOA==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20120113;
        h=date:from:to:cc:message-id:in-reply-to:references:subject
         :mime-version:x-original-sender:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=XczULBTlbSR/r+YGjiGbf/2AArM0f2wIL9i3S1VFoJw=;
        b=msoTQbK7ytgrXG0YjKYysrdSY+xstyLRSomTMN4Duk9h8BF/BWVpXlEwOefd6xcS0B
         j9jJ3A1ea0V+G43QzcFoVRSgMaKdFCm2rv/UsB4LdOzQvAxgFuZ1stJhc8AAJ1SsQgV3
         EiiCPU+0QyoQyKlMXU+k08GKkX3JPYC3v9KXkMYfFypikr1I0o7lYxFcxCSRzEDjrDqF
         mu21XJlyyqb+dV4erqIH0bW7VQ5SI6spmaN2yPzN2pLD19hDawkjaRPjgvA4jLYevkhS
         3zR0jbLNbPoDiY03B/WYJfDPUlgoz6Y+Do7ldKGG9qeHhm/bRSxXNdUhDtymSx1ANPj0
         AX4w==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:date:from:to:cc:message-id:in-reply-to
         :references:subject:mime-version:x-original-sender:reply-to
         :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post
         :list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=XczULBTlbSR/r+YGjiGbf/2AArM0f2wIL9i3S1VFoJw=;
        b=jWO3jIl/ibuqzP8RdwNDkAzOr3+MPftXzmghBCq68K7P9aYV9lt2jWf9Ceo6QHzUan
         IiPdEuzWj1pmSdJog8S819QNE1wu6754SibQwPKPAMz2MbCKmyTFR10+hd/xvG6LUih2
         9GVx6HbKg0tH3i/ATmJRz5UDAIxivxlTxKb5nnwa0jDp5AYeIJ5ceRt1Y4UnqCpKGqI3
         YpcNBBxyGaKnxmVPjMBylFQHVyg1ZopIdDSUPvzYeg3CxPX0NQVdHGyHo9Op6rdFNqj3
         2aoESKaswKx81oaBhponl8F4qo8AehJDRpIIZKMl+qDxDMY32OYzErEdS6fg/lSI2SZ/
         wz2w==
X-Gm-Message-State: AD7BkJIenAw/E+Wi1zBo0TP+dPB/Q25Ek/i0O55lFsjx+fX/YbflcwuCSe97ZstCBehiHQ==
X-Received: by 10.140.253.198 with SMTP id y189mr13511862qhc.9.1456760875238;
        Mon, 29 Feb 2016 07:47:55 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.107.39.206 with SMTP id n197ls1483697ion.52.gmail; Mon, 29 Feb
 2016 07:47:52 -0800 (PST)
X-Received: by 10.50.103.68 with SMTP id fu4mr181545igb.9.1456760872498;
        Mon, 29 Feb 2016 07:47:52 -0800 (PST)
In-Reply-To: <7c6c597d-6d77-4675-8560-295c7feacc04@isocpp.org>
X-Original-Sender: d.h.gottwald@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Spam-Checked-In-Group: std-proposals@isocpp.org
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:24831
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/24831>

------=_Part_179_173916395.1456760871783
Content-Type: multipart/alternative; 
	boundary="----=_Part_180_1243467156.1456760871783"

------=_Part_180_1243467156.1456760871783
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Have you read the paper "How to print floating point numbers accurately",=
=20
e.g. from here: http://kurtstephens.com/files/p372-steele.pdf
This seems to cover some of the problems you described.

On Sunday, February 28, 2016 at 2:06:29 PM UTC+1, u97...@gmail.com wrote:

> This post continues Deprecate to_string() for floating point types?=20
> <https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-disc=
ussion/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()=20
> pointing out it's fundamental problems with floating point types and=20
> suggests a 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>=20
> [6]. Before C++11 there was no clear choice for conversion and some of th=
e=20
> options suggested [4]=20
> <http://stackoverflow.com/questions/5290089/how-to-convert-a-number-to-st=
ring-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 gener=
al=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 type=
s.
>
> 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=
=20
> and 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
>    "100000000000000005250476025520442024870446858110815915491585411551180=
245798890819578637137508044786404370444383288387817694252323536043057564479=
218478670698284838720092657580373783023379478809005936895323497079994508111=
903896764088007465274278014249457925878882005684283811566947219638686545940=
0540160.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 rang=
e=20
> [-308, 308]. All values where exponent is in range [-308, -8] are convert=
ed=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 ran=
ge=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 sour=
ce=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, th=
e=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() impleme=
ntation=20
>    such as stoul(), stoul(to_string(x)) =3D=3D x for all x of type T. In =
plain=20
>    words this means that one can convert integer to string and read it ba=
ck to=20
>    get exactly the same item from which the string representation was cre=
ated=20
>    from. To keep the semantics the same for floating point types, require=
 the=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 tha=
t=20
> to_string(x) =3D=3D to_string(y) for many different x and y thus changing=
 the=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 o=
n=20
> it's implications:
>
>
>    - The string representation is allowed to be ambiguous.
>    - The string representation is not required to be mathematically=20
>    exact: e.g. "1e300" is accepted because from_string(to_string(1e300)) =
=3D=3D=20
>    from_string("1e300") even though mathematically double(1e300) !=3D 1e3=
00.
>    - 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 value=
s 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 ty=
pe=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=
=20
> a (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=
=20
> to 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() return=
s=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 flo=
ating=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 parsin=
g=20
> and avoids possibility for errors in the users defined format string.
>
> -Shortest necessary string representation can't be acquired using=20
> sprintf() with maximal precision, but such implementation would be=20
> acceptable because shortest possible string is not required. This is chos=
en=20
> to avoid the need to define "shortest possible" which is not expected to=
=20
> have essential relevance for the usage of to_string_f(). Also the=20
> implementation effort from library implementers to guarantee the shortest=
=20
> possible on all standard conforming C++ implementations might be=20
> 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 portabili=
ty=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-str=
ing-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/89c4ad80-fd43-4c00-87fd-8dc38ba50739%40isocpp.or=
g.

------=_Part_180_1243467156.1456760871783
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>Have you read the paper &quot;How to print floating p=
oint numbers accurately&quot;, e.g. from here: <a href=3D"http://kurtstephe=
ns.com/files/p372-steele.pdf">http://kurtstephens.com/files/p372-steele.pdf=
</a></div><div>This seems to cover some of the problems you described.<br><=
br>On Sunday, February 28, 2016 at 2:06:29 PM UTC+1, u97...@gmail.com wrote=
:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex=
; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-wid=
th: 1px; border-left-style: solid;"><div dir=3D"ltr">This post continues=C2=
=A0<a onmousedown=3D"this.href=3D&#39;https://groups.google.com/a/isocpp.or=
g/forum/?fromgroups#!topic/std-discussion/6xhWgsEuvPo&#39;;return true;" on=
click=3D"this.href=3D&#39;https://groups.google.com/a/isocpp.org/forum/?fro=
mgroups#!topic/std-discussion/6xhWgsEuvPo&#39;;return true;" href=3D"https:=
//groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-discussion/6x=
hWgsEuvPo" target=3D"_blank" rel=3D"nofollow">Deprecate to_string() for flo=
ating point types?</a><br><br>The original thread served it purpose and it =
seemed more appropriate to start a new thread in this forum with a more pro=
posal-like text for evaluation.<br><br>------------------------<br><br>Summ=
ary<br>--------------<br><br>This document introduces the current behaviour=
 of std::to_string() pointing out it&#39;s fundamental problems with floati=
ng point types and suggests a change to standard.<br><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 onmousedown=3D"this.href=3D&#39;https://=
www.google.com/url?q\75https%3A%2F%2Fisocpp.org%2Fwiki%2Ffaq%2Fnewbie%23int=
-to-string\46sa\75D\46sntz\0751\46usg\75AFQjCNGRrs0D8gCHf_L3woAssxIChXqR_A&=
#39;;return true;" onclick=3D"this.href=3D&#39;https://www.google.com/url?q=
\75https%3A%2F%2Fisocpp.org%2Fwiki%2Ffaq%2Fnewbie%23int-to-string\46sa\75D\=
46sntz\0751\46usg\75AFQjCNGRrs0D8gCHf_L3woAssxIChXqR_A&#39;;return true;" h=
ref=3D"https://isocpp.org/wiki/faq/newbie#int-to-string" target=3D"_blank" =
rel=3D"nofollow">C++ FAQ</a> [6]. Before C++11 there was no clear choice fo=
r conversion and some of the options suggested=C2=A0<a onmousedown=3D"this.=
href=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2F=
questions%2F5290089%2Fhow-to-convert-a-number-to-string-and-vice-versa-in-c=
\46sa\75D\46sntz\0751\46usg\75AFQjCNFlCKhMoCuothv_g6Vy-YlJxppPHQ&#39;;retur=
n true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\75http%3A%=
2F%2Fstackoverflow.com%2Fquestions%2F5290089%2Fhow-to-convert-a-number-to-s=
tring-and-vice-versa-in-c\46sa\75D\46sntz\0751\46usg\75AFQjCNFlCKhMoCuothv_=
g6Vy-YlJxppPHQ&#39;;return true;" href=3D"http://stackoverflow.com/question=
s/5290089/how-to-convert-a-number-to-string-and-vice-versa-in-c" target=3D"=
_blank" rel=3D"nofollow">[4]</a> <a onmousedown=3D"this.href=3D&#39;http://=
www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fquestions%2F332111%=
2Fhow-do-i-convert-a-double-into-a-string-in-c\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHyDCuwvFEuXRS-gnX4sF_EeV9Z4Q&#39;;return true;" onclick=3D"this.href=
=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fques=
tions%2F332111%2Fhow-do-i-convert-a-double-into-a-string-in-c\46sa\75D\46sn=
tz\0751\46usg\75AFQjCNHyDCuwvFEuXRS-gnX4sF_EeV9Z4Q&#39;;return true;" href=
=3D"http://stackoverflow.com/questions/332111/how-do-i-convert-a-double-int=
o-a-string-in-c" target=3D"_blank" rel=3D"nofollow">[5]</a> for the task we=
re:<br><ol><li>std::ostringstream</li><li>sprintf</li><li>boost::lexical_ca=
st</li></ol>These have problems ranging from complexity and 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 point 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>The papers introdu=
cing std::to_string()=C2=A0<a onmousedown=3D"this.href=3D&#39;http://www.go=
ogle.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%=
2Fpapers%2F2005%2Fn1803.html\46sa\75D\46sntz\0751\46usg\75AFQjCNHjrL_pJ-36q=
wuD7j12_iXKbF26sA&#39;;return true;" onclick=3D"this.href=3D&#39;http://www=
..google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdo=
cs%2Fpapers%2F2005%2Fn1803.html\46sa\75D\46sntz\0751\46usg\75AFQjCNHjrL_pJ-=
36qwuD7j12_iXKbF26sA&#39;;return true;" href=3D"http://www.open-std.org/jtc=
1/sc22/wg21/docs/papers/2005/n1803.html" target=3D"_blank" rel=3D"nofollow"=
>[1]</a>=C2=A0<a onmousedown=3D"this.href=3D&#39;http://www.google.com/url?=
q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F20=
06%2Fn1982.html\46sa\75D\46sntz\0751\46usg\75AFQjCNFBfwL0rpTneyr6ayTuGDMTCP=
NzdA&#39;;return true;" onclick=3D"this.href=3D&#39;http://www.google.com/u=
rl?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2=
F2006%2Fn1982.html\46sa\75D\46sntz\0751\46usg\75AFQjCNFBfwL0rpTneyr6ayTuGDM=
TCPNzdA&#39;;return true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/d=
ocs/papers/2006/n1982.html" target=3D"_blank" rel=3D"nofollow">[2]</a>=C2=
=A0<a onmousedown=3D"this.href=3D&#39;http://www.google.com/url?q\75http%3A=
%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2007%2Fn2408.=
html\46sa\75D\46sntz\0751\46usg\75AFQjCNETf6GEwa4_6JF_jadbb9qjoidZ7w&#39;;r=
eturn true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\75http=
%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2007%2Fn24=
08.html\46sa\75D\46sntz\0751\46usg\75AFQjCNETf6GEwa4_6JF_jadbb9qjoidZ7w&#39=
;;return true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/=
2007/n2408.html" target=3D"_blank" rel=3D"nofollow">[3]</a> does not discus=
s the purpose of std::to_string() (i.e. what problem it is intended to solv=
e) and the current standard simply defines that return string of std::to_st=
ring(double val) is identical to what sprintf(buf, &quot;%f&quot;, val) wou=
ld generate with sufficient buffer size buf.<br><br>This paper argues that =
the decision is highly questionable, impractical and a source of bugs thus =
suggesting a change to the standard.<br><br>Problem<br>------------<br><br>=
In form of examples, the definition of std::to_string(double val) essential=
ly as sprintf(buf, &quot;%f&quot;, val) has the following implications:<br>=
<ol><li>std::to_string(double(0)) =3D=3D &quot;0.000000&quot;</li><li>std::=
to_string(double(10000)) =3D=3D &quot;10000.000000&quot;</li><li>std::to_st=
ring(double(1e300)) =3D=3D=20
&quot;<wbr>100000000000000005250476025520<wbr>44202487044685811081591549158=
5<wbr>411551180245798890819578637137<wbr>508044786404370444383288387817<wbr=
>694252323536043057564479218478<wbr>670698284838720092657580373783<wbr>0233=
79478809005936895323497079<wbr>994508111903896764088007465274<wbr>278014249=
457925878882005684283<wbr>811566947219638686545940054016<wbr>0.000000&quot;=
</li><li>std::to_string(double(1e-9)) =3D=3D &quot;0.000000&quot;</li></ol>=
While it&#39;s not obvious how the conversion should work for floating poin=
t types, it&#39;s hard to see that any acceptable implementation would have=
 behaviour as shown above. The problems are:<br><ul><li>Redundant character=
s from information preservation point of view (1, 2, 3, 4).</li><li>Unreada=
ble output (3)</li><li>Failing to preserve even a single significant digit =
(4).</li></ul>While redundant decimal characters may be even desired in som=
e use cases, the failure to preserve any significant digits is a serious is=
sue especially as it is not a rare corner case issue but affects a big prop=
ortion of the whole double domain. How big a proportion? At least in common=
 implementations of double, base 10 exponent can get values in range [-308,=
 308]. All values where exponent is in range [-308, -8] are converted to &q=
uot;0.000000&quot; by std::to_string(). And given that readability of value=
s with tens of digits is bad as demonstrated in example 3, the exponent ran=
ge where std::to_string() creates acceptable string representation 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 related 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 toString() : &quot;1.2=
3456789E-9&quot;</li><li>JavaScript toString() : &quot;1.23456789e-9&quot;<=
/li><li>boost::lexical_cast&lt;std::<wbr>string&gt;(1.23456789e-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.23456789e-9).<wbr>toStr=
ing() : &quot;1.23456789e-09&quot;</li><li>C++ to_string(1.23456789e-9) : &=
quot;0.000000&quot;</li></ul><br>8 implementations, in 5 the result is prec=
ision-wise identical to value written to source code, in 1 the result is no=
n-lossy but longer than source code version, in 1 the value is rounded to 6=
 significant digits and then there&#39;s std::to_string() that simply wipes=
 out all significant digits.<br><br>Ideal<br>-------<br><br>If std::to_stri=
ng() for floating point types was created from scratch, the question would =
be: what should it do? The following starting point is assumed:<br><br><ul>=
<li>std::to_string() for integer types is defined and their implementations=
 are what they currently are.</li><li>to_string() is required to print (hum=
an 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>-----------------=
-------------<wbr>----------<br><br>Big complication is that to_string() ca=
n&#39;t be changed without introducing a (breaking) change. The change coul=
d be of various type:<br><br><ol><li>Behaviour change on runtime: may break=
 any existing code using the current definition.</li><li>Compilation breaki=
ng or deprecation change: safer alternative implemented by API-change causi=
ng a compilation failure.</li><li>Keep current behaviour but introduce para=
meters to make it possible to get a better behaviour.</li></ol><br>Not part=
icularly nice choices, but the runtime behaviour change can be ruled out fo=
r starter leaving only two options. Breaking compilation or deprecation is =
undesired, but preferred to having numerous programmers making bugs due to =
this for decades to come. Thus the proposal is to deprecate current to_stri=
ng for floating point types and introduce a new function with name to_strin=
g_f() or similar that behaves as described earlier. to_string_f() shall als=
o take optional parameters that allows developer to fine tune the conversio=
n like implemented e.g. in=C2=A0 <a onmousedown=3D"this.href=3D&#39;http://=
www.google.com/url?q\75http%3A%2F%2Fdoc.qt.io%2Fqt-5%2Fqstring.html%23numbe=
r-6\46sa\75D\46sntz\0751\46usg\75AFQjCNGB80DqmFeKsIBuDRHvOqvFC7XhFg&#39;;re=
turn true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\75http%=
3A%2F%2Fdoc.qt.io%2Fqt-5%2Fqstring.html%23number-6\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNGB80DqmFeKsIBuDRHvOqvFC7XhFg&#39;;return true;" href=3D"http://d=
oc.qt.io/qt-5/qstring.html#number-6" target=3D"_blank" rel=3D"nofollow">QSt=
ring::number()</a> [7]. Options for fine tuning is important in the sense t=
hat making to_string_f() too simple and restricted will too quickly cause p=
rogrammer to resort to old and lacking alternatives, although at this point=
 the purpose of to_string_f() is not to act as full featured sprintf-like f=
ormatting implementation.<br><br>Early draft suggestion<br>----------------=
--------------<wbr>-<br><br>(float, long double and wstring omitted for cla=
rity):<br><br>std::string to_string_f(double d, int precision =3D special_v=
alue_requesting_<wbr>shortest_nonlossy_<wbr>representation, char format =3D=
 &#39;g&#39;) noexcept;<br><br>Precision: Meaning depends on format-specifi=
er 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 f=
ormat is not within accepted range, to_string_f() returns empty string.<br>=
<br><br>Notes and open questions<br>------------------------------<wbr>----=
----<br><br>-Usage examples and possible return values:<br>=C2=A0=C2=A0=C2=
=A0 to_string_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&#39;) -&gt; &quot;1.00&quot;<br>=C2=A0=C2=A0=C2=A0 to_string_f(1.234=
56789e-9) -&gt; &quot;1.23456789e-9&quot;<br>=C2=A0=C2=A0=C2=A0 to_string_f=
(1.23456789e-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 all the possible floating point implementations permitted by the C++=
 standard? If not, can the condition be fulfilled by not requiring it for s=
ome corner 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 ne=
ed to do string parsing and avoids possibility for errors in the users defi=
ned format string.<br><br>-Shortest necessary string representation can&#39=
;t be acquired using sprintf() with maximal precision, but such implementat=
ion would be acceptable because shortest possible string is not required. T=
his is chosen to avoid the need to define &quot;shortest possible&quot; whi=
ch is not expected to have essential relevance for the usage of to_string_f=
(). Also the implementation effort from library implementers to guarantee t=
he shortest possible on all standard conforming C++ implementations might b=
e unnecessarily high.<br><br>-For portability of string representation, see=
 the end of section &#39;Ideal&#39;<br><br>-Should the default value for pr=
ecision be, 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 rev=
ised 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 output is locale independent? Locale-dependency would cause portability=
 issues so having locale-independent output would be desirable and in accor=
dance with the design intention as to_string_f() is not intended to do full=
 featured locale aware formatting.<br><br>-Would to_string_f() be appropria=
te name?<br><br><br>Details on examples<br>-----------------------------<br=
><br>Visual 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 Di=
m s As String =3D aDouble.ToString()<br>=C2=A0=C2=A0=C2=A0 Console.WriteLin=
e(s)<br>=C2=A0=C2=A0=C2=A0 <br>C# (VS2015)<br>=C2=A0=C2=A0=C2=A0 double a =
=3D 1.23456789e-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 (boost 1.55)<br>=C2=A0=C2=A0=C2=A0 auto s =3D boost::lexical_cast&lt;s=
td::<wbr>string&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 Do=
uble a =3D 1.23456789e-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>Java=
Script (tested 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 <b=
r>Qt (5.4)<br>=C2=A0=C2=A0=C2=A0 QString s =3D QString::number(1.23456789e-=
9)<wbr>;<br>=C2=A0=C2=A0=C2=A0 auto s2 =3D QVariant(1.23456789e-9).<wbr>toS=
tring();<br><br><br>References<br>----------<br><br>[1] N1803: Simple Numer=
ic Access. <a onmousedown=3D"this.href=3D&#39;http://www.google.com/url?q\7=
5http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2005%=
2Fn1803.html\46sa\75D\46sntz\0751\46usg\75AFQjCNHjrL_pJ-36qwuD7j12_iXKbF26s=
A&#39;;return true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?=
q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F20=
05%2Fn1803.html\46sa\75D\46sntz\0751\46usg\75AFQjCNHjrL_pJ-36qwuD7j12_iXKbF=
26sA&#39;;return true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs=
/papers/2005/n1803.html" target=3D"_blank" rel=3D"nofollow">http://www.open=
-std.org/jtc1/<wbr>sc22/wg21/docs/papers/2005/<wbr>n1803.html</a><br>[2] N1=
982: Simple Numeric Access Revision 1. <a onmousedown=3D"this.href=3D&#39;h=
ttp://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2F=
wg21%2Fdocs%2Fpapers%2F2006%2Fn1982.html\46sa\75D\46sntz\0751\46usg\75AFQjC=
NFBfwL0rpTneyr6ayTuGDMTCPNzdA&#39;;return true;" onclick=3D"this.href=3D&#3=
9;http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22=
%2Fwg21%2Fdocs%2Fpapers%2F2006%2Fn1982.html\46sa\75D\46sntz\0751\46usg\75AF=
QjCNFBfwL0rpTneyr6ayTuGDMTCPNzdA&#39;;return true;" href=3D"http://www.open=
-std.org/jtc1/sc22/wg21/docs/papers/2006/n1982.html" target=3D"_blank" rel=
=3D"nofollow">http://www.open-std.org/jtc1/<wbr>sc22/wg21/docs/papers/2006/=
<wbr>n1982.html</a><br>[3] N2408: Simple Numeric Access Revision 2. <a onmo=
usedown=3D"this.href=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.=
open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2007%2Fn2408.html\46sa\=
75D\46sntz\0751\46usg\75AFQjCNETf6GEwa4_6JF_jadbb9qjoidZ7w&#39;;return true=
;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fw=
ww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2007%2Fn2408.html\46=
sa\75D\46sntz\0751\46usg\75AFQjCNETf6GEwa4_6JF_jadbb9qjoidZ7w&#39;;return t=
rue;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2408=
..html" target=3D"_blank" rel=3D"nofollow">http://www.open-std.org/jtc1/<wbr=
>sc22/wg21/docs/papers/2007/<wbr>n2408.html</a><br>[4] How to convert a num=
ber to string and vice versa in C++. <a onmousedown=3D"this.href=3D&#39;htt=
p://www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fquestions%2F529=
0089%2Fhow-to-convert-a-number-to-string-and-vice-versa-in-c\46sa\75D\46snt=
z\0751\46usg\75AFQjCNFlCKhMoCuothv_g6Vy-YlJxppPHQ&#39;;return true;" onclic=
k=3D"this.href=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fstackoverf=
low.com%2Fquestions%2F5290089%2Fhow-to-convert-a-number-to-string-and-vice-=
versa-in-c\46sa\75D\46sntz\0751\46usg\75AFQjCNFlCKhMoCuothv_g6Vy-YlJxppPHQ&=
#39;;return true;" href=3D"http://stackoverflow.com/questions/5290089/how-t=
o-convert-a-number-to-string-and-vice-versa-in-c" target=3D"_blank" rel=3D"=
nofollow">http://stackoverflow.com/<wbr>questions/5290089/how-to-<wbr>conve=
rt-a-number-to-string-<wbr>and-vice-versa-in-c</a><br>[5] How do I convert =
a double into a string in C++?. <a onmousedown=3D"this.href=3D&#39;http://w=
ww.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fquestions%2F332111%2=
Fhow-do-i-convert-a-double-into-a-string-in-c\46sa\75D\46sntz\0751\46usg\75=
AFQjCNHyDCuwvFEuXRS-gnX4sF_EeV9Z4Q&#39;;return true;" onclick=3D"this.href=
=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fques=
tions%2F332111%2Fhow-do-i-convert-a-double-into-a-string-in-c\46sa\75D\46sn=
tz\0751\46usg\75AFQjCNHyDCuwvFEuXRS-gnX4sF_EeV9Z4Q&#39;;return true;" href=
=3D"http://stackoverflow.com/questions/332111/how-do-i-convert-a-double-int=
o-a-string-in-c" target=3D"_blank" rel=3D"nofollow">http://stackoverflow.co=
m/<wbr>questions/332111/how-do-i-<wbr>convert-a-double-into-a-<wbr>string-i=
n-c</a><br>[6] How do I convert an integer to a string? <a onmousedown=3D"t=
his.href=3D&#39;https://www.google.com/url?q\75https%3A%2F%2Fisocpp.org%2Fw=
iki%2Ffaq%2Fnewbie%23int-to-string\46sa\75D\46sntz\0751\46usg\75AFQjCNGRrs0=
D8gCHf_L3woAssxIChXqR_A&#39;;return true;" onclick=3D"this.href=3D&#39;http=
s://www.google.com/url?q\75https%3A%2F%2Fisocpp.org%2Fwiki%2Ffaq%2Fnewbie%2=
3int-to-string\46sa\75D\46sntz\0751\46usg\75AFQjCNGRrs0D8gCHf_L3woAssxIChXq=
R_A&#39;;return true;" href=3D"https://isocpp.org/wiki/faq/newbie#int-to-st=
ring" target=3D"_blank" rel=3D"nofollow">https://isocpp.org/wiki/faq/<wbr>n=
ewbie#int-to-string</a><br>[7] QString::number(). <a onmousedown=3D"this.hr=
ef=3D&#39;http://www.google.com/url?q\75http%3A%2F%2Fdoc.qt.io%2Fqt-5%2Fqst=
ring.html%23number-6\46sa\75D\46sntz\0751\46usg\75AFQjCNGB80DqmFeKsIBuDRHvO=
qvFC7XhFg&#39;;return true;" onclick=3D"this.href=3D&#39;http://www.google.=
com/url?q\75http%3A%2F%2Fdoc.qt.io%2Fqt-5%2Fqstring.html%23number-6\46sa\75=
D\46sntz\0751\46usg\75AFQjCNGB80DqmFeKsIBuDRHvOqvFC7XhFg&#39;;return true;"=
 href=3D"http://doc.qt.io/qt-5/qstring.html#number-6" target=3D"_blank" rel=
=3D"nofollow">http://doc.qt.io/qt-5/qstring.<wbr>html#number-6</a>.<br>=C2=
=A0=C2=A0=C2=A0 <br></div></blockquote></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/89c4ad80-fd43-4c00-87fd-8dc38ba50739%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/89c4ad80-fd43-4c00-87fd-8dc38ba50739=
%40isocpp.org</a>.<br />

------=_Part_180_1243467156.1456760871783--
------=_Part_179_173916395.1456760871783--

.
