3

I'm trying to convert C# double values to string of exponential notation. Consider this C# code:

double d1 = 0.12345678901200021;
Console.WriteLine(d1.ToString("0.0####################E0"));
//outputs: 1.23456789012E-1 (expected: 1.2345678901200021E-1)

Can anyone tell me the format string to output "1.2345678901200021E-1" from double d1, if it's possible?

svick
  • 236,525
  • 50
  • 385
  • 514
danze
  • 745
  • 2
  • 10
  • 24
  • 7
    A `double` doesn't have that much precision. If you want to keep all those digits, you should use `decimal` instead. – Jon Skeet Jun 11 '13 at 19:52
  • 2
    @JonSkeet As far as I can see, this is right at the edge of `double`'s precision. So, `0.12345678901200021 == 0.12345678901200020`, but `0.12345678901200021 != 0.12345678901200019` and `0.12345678901200021 != 0.12345678901200022`. – svick Jun 11 '13 at 20:02
  • @JonSkeet Interesting, I'm porting some Java app and expected C# to print the whole value (Java prints as expected). – danze Jun 11 '13 at 20:03
  • @daniel.tekle: It's just as broken in Java - you're still expecting too much precision. – Jon Skeet Jun 11 '13 at 20:11
  • @JonSkeet Anyways I changed it to decimal. Thx, but I can't give the answer to you since you answered it in a comment? – danze Jun 11 '13 at 20:20
  • @daniel.tekle: It's fine - Robbert's answer is good :) – Jon Skeet Jun 11 '13 at 20:30

5 Answers5

3

Double values only hold 15 to 16 digits, you have 17 (if I counted right). Because 64 bit double numbers only hold 16 digits, your last digit is getting truncated and therefore when you convert the number to scientific notation, the last digit appears to have been truncated.

You should use Decimal instead. Decimal types can hold 128 bits of data, while double can only hold 64 bits.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Robbert
  • 6,481
  • 5
  • 35
  • 61
  • 1
    But the output omits at least two digits (`21`), not just the last one, like you claim. – svick Jun 11 '13 at 20:04
  • Even after changed it to decimal? – Robbert Jun 11 '13 at 20:07
  • I meant just when using `double`. According to you, the output should be something like `1.234567890120002E-1`, but it's actually `1.23456789012E-1`. – svick Jun 11 '13 at 20:10
  • @Robbert after changing it to decimal its printing the whole value. But I agree with svick (I expected it to print atleast 1.234567890120002E-1) thus why I asked the question – danze Jun 11 '13 at 20:11
  • I've found conflicting information about the number of digits a double can hold. If it's 15, then the last two digits of your number would be truncated leaving you with three 0s at the end, which would usually get removed as trailing 0s usually are. Sorry, I don't have an exact answer for you there. – Robbert Jun 11 '13 at 20:22
  • 1
    @Robbert `double` doesn't contain digits, it contains bits. If you convert the bits to digits, you come up with ~ 15.9. The specific number of whole digits depends on the value of the first significant digit. If it's small enough, 16 whole digits (plus a part of 17th) will fit into the `double`. – svick Jun 11 '13 at 20:39
2

According to the documentation for double.ToString(), double doesn't have the precision:

By default, the return value only contains 15 digits of precision although a maximum of 17 digits is maintained internally. If the value of this instance has greater than 15 digits, ToString returns PositiveInfinitySymbol or NegativeInfinitySymbol instead of the expected number. If you require more precision, specify format with the "G17" format specification, which always returns 17 digits of precision, or "R", which returns 15 digits if the number can be represented with that precision or 17 digits if the number can only be represented with maximum precision.

svick
  • 236,525
  • 50
  • 385
  • 514
Stephen King
  • 816
  • 4
  • 14
1

Console.WriteLine(d1) should show you that double doesn't support your wanted precision. Use decimal instead (64bit vs 128bit).

Sebastian
  • 5,177
  • 4
  • 30
  • 47
1

My immediate window is saying that the maximum resolution you can expect from that double number is about 15 digits.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
0

My VS2012 immediate window is saying that the resolution of 0.12345678901200021 is actually 16 significant digits:

0.1234567890120002

Therefore we expect that at least the last "2" digit should be reported in the string.

However if you use the "G17" format string:

0.12345678901200021D.ToString("G17");

you will get a string with 16 digit precision. See this answer.

Community
  • 1
  • 1
Luca Cremonesi
  • 144
  • 2
  • 3
  • 13