0

So, WPF calls ToString() on objects when generating TextColumns in DataGrid and then i found out strange thing about ToString() method: Check this out :

object a = 0.3780000001;//Something like this
Console.WriteLine(a.ToString());//Gets truncated in some cases

First, I thought it was just rounding, but few times I was able to reproduce such behavior on doubles with < 15 digits after dot. Am I missing something?

illegal-immigrant
  • 8,089
  • 9
  • 51
  • 84
  • 11
    Not a .NET bug, just rounding issues. – BoltClock Jan 13 '11 at 16:54
  • 3
    Please read the answers. **Double is not an appropriate type to use if you want to deal with both high precision and high accuracy. Use `decimal`.** – Adam Robinson Jan 13 '11 at 17:39
  • OK, thanks, I just thought some WPF solution to always show 17 digits after dot when rendering cell exists – illegal-immigrant Jan 13 '11 at 17:44
  • @taras: The point is that this has nothing to do with WPF or the UI *at all*. It's simply not there in the *data type*. – Adam Robinson Jan 13 '11 at 17:45
  • Now I understand this, numbers with >17 digits after dot simply are getting rounded when ToString() is called – illegal-immigrant Jan 13 '11 at 17:47
  • 1
    @taras: No, that's not correct. There is no rounding happening when you call `ToString()`, as values with >17 significant digits (according to the spec, actually, >15 significant digits) *are truncated when they're stored*. There's no rounding taking place because the value simply doesn't exist. – Adam Robinson Jan 13 '11 at 17:54

9 Answers9

9

To the computer, 0.378 and 0.378000...0001 are the same number. See this question: Why is floating point arithmetic in C# imprecise?

Community
  • 1
  • 1
Tim Robinson
  • 53,480
  • 10
  • 121
  • 138
  • Strictly speaking, that's not true. `0.378` and `0.378....0001` may *or may not* have the same in-memory representation. In the case of a sufficiently-large `decimal` in .NET, they're certainly different. In the case of any of the floating-point types in .NET, they're the same. – Adam Robinson Jan 13 '11 at 17:07
4

Use decimal instead of float for a more precise type.

Nekresh
  • 2,948
  • 23
  • 28
4

As defined on the MSDN page for System.Double, the double type only contains a maximum of fifteen digits of precision. Even though it maintains 17 internally, your figure contains 18 significant digits; this is outside the range of System.Double.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
3

By default, Double.ToString() truncates to 15 digits after the dot, but if you really want to use the double data type and you need those 2 extra digits, you can use th "G17" formatting string:

double x = 3.1415926535897932;

string pi = x.ToString("G17");

This will give you a string with the full 17 digits.

Trystan
  • 31
  • 1
2

I wouldn't assume (so fast) that you found a bug in something as crucial as C#'s ToString implementation.

The behaviour you're experiencing is caused by the fact that a float is imprecisely stored in computer memory (also see this question).

Community
  • 1
  • 1
ChristopheD
  • 112,638
  • 29
  • 165
  • 179
1

maybe the number format's accuracy range doesn't contain that number? (ie, float only has accuracy to a few significant figures)

Kurru
  • 14,180
  • 18
  • 64
  • 84
1

If you're data-binding the value, you can supply a ValueConverter which formats the number any way you want.

http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx

Mark Rendle
  • 9,274
  • 1
  • 32
  • 58
1

Set a to be an Decimal and it will print it correctly!

decimal a = 0.378000000000000001m;
    Console.WriteLine(a.ToString()); 
StefanE
  • 7,578
  • 10
  • 48
  • 75
0

You could have a common decimal format setting to use all the time.

eg


 object a = 0.378000000000000001;
 Console.WriteLine(a.ToString(Settings.DecimalFormat));
WraithNath
  • 17,658
  • 10
  • 55
  • 82