# double to string retain "precision"

Discussion in 'C++' started by rjsteele, Mar 10, 2011.

1. ### rjsteeleGuest

How do I retain the value (precision) of the double as a string?

double d = 117.9879878988754135
stringstream ss;
ss << d;

cout << ss.str() << endl;

Output: 117.987 ---------- I want this to be the same as the
initial double.

rjsteele, Mar 10, 2011

2. ### rjsteeleGuest

On Mar 9, 5:00 pm, rjsteele <> wrote:
> How do I retain the value (precision) of the double as a string?
>
> double d = 117.9879878988754135
> stringstream ss;
> ss << d;
>
> cout << ss.str()  << endl;
>
> Output:   117.987  ---------- I want this to be the same as the
> initial double.
>

I think I go it.

std::stringstream ss; ss <<
std::setprecision(std::numeric_limits<double>::digits10); ss << d;
return ss.str();

rjsteele, Mar 10, 2011

3. ### SGGuest

rjsteele wrote:
> rjsteele wrote:
>
> > How do I retain the value (precision) of the double as a string?

>
> I think I go it.
>
>  std::stringstream ss;
> ss << std::setprecision(std::numeric_limits<double>::digits10);
> ss << d;
> return ss.str();

I don't recall how exactly digits10 was defined but in case double
refers to an IEEE-754 64-bit float on your machine, you will need 17
significant decimal digits for a lossless double-string-double
roundtrip. For a lossless string-double-string roundtrip (*) you need
to limit your strings to 15 significant decimal digits

(* lossless in the sense that the numbers the strings represent are
the same and not necessarily the strings itself, so "0.15" would be
equal to "0.1500" for example)

Cheers!
SG

SG, Mar 10, 2011
4. ### Juha NieminenGuest

rjsteele <> wrote:
> How do I retain the value (precision) of the double as a string?

In general, you can't. Most floating point values have an infinite
decimal representation.

If you want a certain amount of decimals, use the precision()
modifier.

Juha Nieminen, Mar 10, 2011
5. ### Fred ZwartsGuest

"Juha Nieminen" <> wrote in message
news:4d7886fa\$0\$2892\$
> rjsteele <> wrote:
>> How do I retain the value (precision) of the double as a string?

>
> In general, you can't. Most floating point values have an infinite
> decimal representation.

No. In many cases foating point values are stored as finite numbers with base 2.
As 2 is a divisor of 10, a finite number in base 2 can be represented as a finite number in base 10.
(But not the other way around. 1/5 = 0.2 is not a finite number in base 2.)

Fred Zwarts, Mar 10, 2011
6. ### James KanzeGuest

On Mar 10, 8:08 am, Juha Nieminen <> wrote:
> rjsteele <> wrote:
> > How do I retain the value (precision) of the double as a string?

> In general, you can't. Most floating point values have an infinite
> decimal representation.

No. All can be represented exactly: ten is a multiple of 2, so for n
bits precision in machine format, you are guaranteed an exact
representation with at most n decimal digits.

Of course, n is typically 52, and only a very small subset of 52 digit
numbers correspond exactly to a double. And since in most cases, it's
highly unlikely that the double corresponded to the exact value to
begin
with, you don't use 52 digits.

--
James Kanze

James Kanze, Mar 10, 2011
7. ### Öö TiibGuest

On Mar 10, 10:59 pm, James Kanze <> wrote:
> On Mar 10, 8:08 am, Juha Nieminen <> wrote:
>
> > rjsteele <> wrote:
> > > How do I retain the value (precision) of the double as a string?

> > In general, you can't. Most floating point values have an infinite
> > decimal representation.

>
> No.  All can be represented exactly: ten is a multiple of 2, so for n
> bits precision in machine format, you are guaranteed an exact
> representation with at most n decimal digits.
>
> Of course, n is typically 52, and only a very small subset of 52 digit
> numbers correspond exactly to a double.  And since in most cases, it's
> highly unlikely that the double corresponded to the exact value to
> begin
> with, you don't use 52 digits.

52 decimal digits? That means your float types have over 180 bits?

Öö Tiib, Mar 11, 2011
8. ### rjsteeleGuest

On Mar 10, 5:49 pm, Öö Tiib <> wrote:
> On Mar 10, 10:59 pm, James Kanze <> wrote:
>
>
>
>
>
> > On Mar 10, 8:08 am, Juha Nieminen <> wrote:

>
> > > rjsteele <> wrote:
> > > > How do I retain the value (precision) of the double as a string?
> > > In general, you can't. Most floating point values have an infinite
> > > decimal representation.

>
> > No.  All can be represented exactly: ten is a multiple of 2, so for n
> > bits precision in machine format, you are guaranteed an exact
> > representation with at most n decimal digits.

>
> > Of course, n is typically 52, and only a very small subset of 52 digit
> > numbers correspond exactly to a double.  And since in most cases, it's
> > highly unlikely that the double corresponded to the exact value to
> > begin
> > with, you don't use 52 digits.

>
> 52 decimal digits? That means your float types have over 180 bits?

Thanks for all the responses.

rjsteele, Mar 11, 2011
9. ### Keith H DuggarGuest

On Mar 9, 7:06 pm, rjsteele <> wrote:
> On Mar 9, 5:00 pm, rjsteele <> wrote:
>
> > How do I retain the value (precision) of the double as a string?

>
> > double d = 117.9879878988754135
> > stringstream ss;
> > ss << d;

>
> > cout << ss.str()  << endl;

>
> > Output:   117.987  ---------- I want this to be the same as the
> > initial double.

>

>
> I think I go it.
>
>  std::stringstream ss;   ss <<
> std::setprecision(std::numeric_limits<double>::digits10);   ss << d;
> return ss.str();

Use

std::numeric_limits<double>::digits10 + 1

KHD

Keith H Duggar, Mar 11, 2011
10. ### Fred ZwartsGuest

"Öö Tiib" <> wrote in message
news:
> On Mar 10, 10:59 pm, James Kanze <> wrote:
>> On Mar 10, 8:08 am, Juha Nieminen <> wrote:
>>
>>> rjsteele <> wrote:
>>>> How do I retain the value (precision) of the double as a string?
>>> In general, you can't. Most floating point values have an infinite
>>> decimal representation.

>>
>> No. All can be represented exactly: ten is a multiple of 2, so for n
>> bits precision in machine format, you are guaranteed an exact
>> representation with at most n decimal digits.
>>
>> Of course, n is typically 52, and only a very small subset of 52
>> digit numbers correspond exactly to a double. And since in most
>> cases, it's highly unlikely that the double corresponded to the
>> exact value to begin
>> with, you don't use 52 digits.

>
> 52 decimal digits? That means your float types have over 180 bits?

No.

n bits corresponds with n decimal digits if printed in full precision.
Numbers are nomally normalized such that the mantisse is a fractional
number 0.5 <= M < 0.25.
Each bit corresponds with one of the following values:

1/2 = 0.5
1/4 = 0.25
1/8 = 0.125
etc.

The position of the last decimal shifts one place to the right for each bit..
Since the bit for the value 1/2 is always non-zero,
the total length of the decimal representation is always smaller or equal to
the number of bits.

Fred Zwarts, Mar 11, 2011
11. ### Fred ZwartsGuest

"Fred Zwarts" <> wrote in message
news:ildds2\$129\$
> "Öö Tiib" <> wrote in message
> news:
>> On Mar 10, 10:59 pm, James Kanze <> wrote:
>>> On Mar 10, 8:08 am, Juha Nieminen <> wrote:
>>>
>>>> rjsteele <> wrote:
>>>>> How do I retain the value (precision) of the double as a string?
>>>> In general, you can't. Most floating point values have an infinite
>>>> decimal representation.
>>>
>>> No. All can be represented exactly: ten is a multiple of 2, so for n
>>> bits precision in machine format, you are guaranteed an exact
>>> representation with at most n decimal digits.
>>>
>>> Of course, n is typically 52, and only a very small subset of 52
>>> digit numbers correspond exactly to a double. And since in most
>>> cases, it's highly unlikely that the double corresponded to the
>>> exact value to begin
>>> with, you don't use 52 digits.

>>
>> 52 decimal digits? That means your float types have over 180 bits?

>
> No.
>
> n bits corresponds with n decimal digits if printed in full precision.
> Numbers are nomally normalized such that the mantisse is a fractional
> number 0.5 <= M < 0.25.

Sorry, that should be 1 < M <= 0.5.
The bit for the value 1/2 is always non-zero.

> Each bit corresponds with one of the following values:
>
> 1/2 = 0.5
> 1/4 = 0.25
> 1/8 = 0.125
> etc.
>
> The position of the last decimal shifts one place to the right for
> each bit.. Since the bit for the value 1/2 is always non-zero,
> the total length of the decimal representation is always smaller or
> equal to the number of bits.

Fred Zwarts, Mar 11, 2011
12. ### Juha NieminenGuest

James Kanze <> wrote:
> On Mar 10, 8:08 am, Juha Nieminen <> wrote:
>> rjsteele <> wrote:
>> > How do I retain the value (precision) of the double as a string?

>
>> In general, you can't. Most floating point values have an infinite
>> decimal representation.

>
> No. All can be represented exactly: ten is a multiple of 2,

I suppose I'll have to stand corrected. I got confused by the
conversion in the other direction (ie. not all values in base 10
can be represented as floating point of base 2).

> so for n
> bits precision in machine format, you are guaranteed an exact
> representation with at most n decimal digits.

Only if you use the exponential notation (ie. "<base>e<exponent>").
If you wrote it as a decimal value, it could take hundreds of digits
(after all, the maximum value of a double-precision floating point is
something like 10^300).

Juha Nieminen, Mar 11, 2011
13. ### James KanzeGuest

On Mar 11, 4:53 pm, Juha Nieminen <> wrote:
> James Kanze <> wrote:
> > On Mar 10, 8:08 am, Juha Nieminen <> wrote:
> >> rjsteele <> wrote:
> >> > How do I retain the value (precision) of the double as a string?

> >> In general, you can't. Most floating point values have an infinite
> >> decimal representation.

> > No. All can be represented exactly: ten is a multiple of 2,

> I suppose I'll have to stand corrected. I got confused by the
> conversion in the other direction (ie. not all values in base
> 10 can be represented as floating point of base 2).

> > so for n bits precision in machine format, you are
> > guaranteed an exact representation with at most n decimal
> > digits.

> Only if you use the exponential notation (ie.
> "<base>e<exponent>"). If you wrote it as a decimal value, it
> could take hundreds of digits (after all, the maximum value of
> a double-precision floating point is something like 10^300).

Good point. But it's worse than you think: the generated
notation has nothing to do with; the only important part is the
actual value. For an IEEE double:

-- If the value is between 0.5 and 1.0 (logical exponent 0),
the value can be written exactly in at most 53 digits, for
the reason I explained.

-- If the value is larger than 2^53, the exact value is an
integer. Since DBL_MAX is something e307, it takes at most
307 digits. On the other hand, the value can be 2^1023
(even larger in fact, but less than 2^1024), and 2^1023
requires 308 digits to represent exactly. (The value is
roughly 9e307, and is not a multiple of 10, so will require
a units digit which is not 0.) Thus, there are values which
require 308 digits.

-- For exponents less than 0, I'm too lazy to do the exact
analysis, but I get the feeling that they will never require
more digits than 308. Unlike positive values, increasing
the binary exponant quickly starts introducing 0's to the
right of the decimal. I'll leave the detailed analysis and
the proof to others, but I'm fairly convinced that it can't
be worse than 308 + 53. Which is still a finit number of
digits.

--
James Kanze

James Kanze, Mar 11, 2011
14. ### Jorgen GrahnGuest

On Thu, 2011-03-10, Juha Nieminen wrote:
> rjsteele <> wrote:
>> How do I retain the value (precision) of the double as a string?

>
> In general, you can't. Most floating point values have an infinite
> decimal representation.

But all of them have a finite hexadecimal representation. I don't
remember if those are part of C++ (they are in C99) and I have no idea
how to print in that format using iostreams, and they would be
unreadable for normal people ... but if you need "lossless printing"
that's an option.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Jorgen Grahn, Mar 13, 2011
15. ### Jorgen GrahnGuest

On Sun, 2011-03-13, Jorgen Grahn wrote:
> On Thu, 2011-03-10, Juha Nieminen wrote:
>> rjsteele <> wrote:
>>> How do I retain the value (precision) of the double as a string?

>>
>> In general, you can't. Most floating point values have an infinite
>> decimal representation.

>
> But all of them have a finite hexadecimal representation. I don't
> remember if those are part of C++ (they are in C99) and I have no idea
> how to print in that format using iostreams, and they would be
> unreadable for normal people ... but if you need "lossless printing"
> that's an option.

And now I saw the other part of the thread, e.g.
<4d7a5386\$0\$2814\$>. Ah, I made the same mistake as
Juha.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Jorgen Grahn, Mar 13, 2011
16. ### Öö TiibGuest

On Mar 13, 4:49 pm, Pete Becker <> wrote:
> > On Thu, 2011-03-10, Juha Nieminen wrote:
> >> rjsteele <> wrote:
> >>> How do I retain the value (precision) of the double as a string?

>
> >> In general, you can't. Most floating point values have an infinite
> >> decimal representation.

>
> The thing to keep in mind here is that because of the limited precision
> of the floating-point value it doesn't necessarily represent the
> "exact" result (i.e. the result you'd get with unbounded precision). In
> many cases, if you've done the math correctly, the result is the
> floating-point value that's closest to the true value. When you convert
> that value to decimal you can't get the "exact" result; it just isn't
> there. Instead, you should get a decimal representation that can be
> converted back to floating-point and give you the original
> floating-point value. There are lots of decimal values that will
> satisfy that requirement, and there's no good reason to choose one with
> lots of digits over one with fewer.

Yes but if to think of it then they are right that IEEE doubles do
have always finite decimal representation, so exact result is always
there. Reverse is not true so majority of decimal values can not be
represented as exact IEEE doubles.

Öö Tiib, Mar 13, 2011
17. ### Fred ZwartsGuest

"Pete Becker" <> wrote in message
news:201103131354034756-pete@versatilecodingcom
> On 2011-03-13 12:01:38 -0400, Öö Tiib said:
>
>> On Mar 13, 4:49 pm, Pete Becker <> wrote:
>>>> On Thu, 2011-03-10, Juha Nieminen wrote:
>>>>> rjsteele <> wrote:
>>>>>> How do I retain the value (precision) of the double as a string?
>>>
>>>>> In general, you can't. Most floating point values have an infinite
>>>>> decimal representation.
>>>
>>> The thing to keep in mind here is that because of the limited
>>> precision of the floating-point value it doesn't necessarily
>>> represent the "exact" result (i.e. the result you'd get with
>>> unbounded precision). In many cases, if you've done the math
>>> correctly, the result is the floating-point value that's closest to
>>> the true value. When you convert that value to decimal you can't
>>> get the "exact" result; it just isn't there. Instead, you should
>>> get a decimal representation that can be converted back to
>>> floating-point and give you the original floating-point value.
>>> There are lots of decimal values that will satisfy that
>>> requirement, and there's no good reason to choose one with lots of
>>> digits over one with fewer.

>>
>> Yes but if to think of it then they are right that IEEE doubles do
>> have always finite decimal representation, so exact result is always
>> there.

>
> I think that's what I just said, although I don't know who "they" are.
> You can always create a finite decimal representation that can be
> translated back to the original floating-point value.

Not only one that can be translated back to the same original floating point number
(after rounding), but even one that represents exactly the same value (without rounding).
Only the representation differs, the value of the decimal representation is exactly the same
as that of the original (binairy) floating point representation.
There is only one decimal representation that exactly matches the binairy representation.
(There are, of course, many that match within the precision of the binairy representation.)

Fred Zwarts, Mar 14, 2011
18. ### James KanzeGuest

On Mar 13, 7:38 am, Jorgen Grahn <> wrote:
> On Thu, 2011-03-10, Juha Nieminen wrote:
> > rjsteele <> wrote:
> >> How do I retain the value (precision) of the double as a string?

> > In general, you can't. Most floating point values have an infinite
> > decimal representation.

> But all of them have a finite hexadecimal representation.

Maybe. I've worked on machines which used a decimal floating
point format (but that was long before C++). A decimal floating
point will not have a finite hexadecimal representation (0.2,
for example), since the prime factors of 10 are 2 and 5, and 1/5
doesn't have a finite hexadecimal representation. (A binary
floating point will have a finite decimal representation, since
2 is a factor of 10.)

> I don't
> remember if those are part of C++ (they are in C99) and I have no idea
> how to print in that format using iostreams, and they would be
> unreadable for normal people ... but if you need "lossless printing"
> that's an option.

They're not part of C++, and as for lossless... If you write and
then read on the same machine, you can obtain "lossless" for any
base. If you don't, what does it mean: you write from a machine
with 120 floating point (double on an old CDC, for example), and
you read on a machine with 64 bit doubles. How can you obtain
lossless?

--
James Kanze

James Kanze, Mar 14, 2011