double to string retain "precision"

R

rjsteele

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.

Thanks in advance.
 
R

rjsteele

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.

Thanks in advance.

I think I go it.

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

SG

rjsteele said:
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
 
J

Juha Nieminen

rjsteele said:
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.
 
F

Fred Zwarts

Juha Nieminen said:
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.)
 
J

James Kanze

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.
 
Ö

Öö Tiib

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?
 
K

Keith H Duggar

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

instead.

KHD
 
F

Fred Zwarts

Öö Tiib said:
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.
 
F

Fred Zwarts

Fred Zwarts said:
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.
 
J

Juha Nieminen

James Kanze said:
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).
 
J

James Kanze

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).
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.
 
J

Jorgen Grahn

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
 
J

Jorgen Grahn

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.
<[email protected]>. Ah, I made the same mistake as
Juha.

/Jorgen
 
Ö

Öö Tiib

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.
 
F

Fred Zwarts

Pete Becker said:
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.)
 
J

James Kanze

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?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top