8

Let's say we have the following simple code

        string number = "93389.429999999993";
        double numberAsDouble = Convert.ToDouble(number);
        Console.WriteLine(numberAsDouble);

after that conversion numberAsDouble variable has the value 93389.43. What can i do to make this variable keep the full number as is without rounding it? I have found that Convert.ToDecimal does not behave the same way but i need to have the value as double.

-------------------small update---------------------

putting a breakpoint in line 2 of the above code shows that the numberAsDouble variable has the rounded value 93389.43 before displayed in the console.

Giorgos Manoltzas
  • 1,710
  • 5
  • 24
  • 34

7 Answers7

11

93389.429999999993 cannot be represented exactly as a 64-bit floating point number. A double can only hold 15 or 16 digits, while you have 17 digits. If you need that level of precision use a decimal instead.

(I know you say you need it as a double, but if you could explain why, there may be alternate solutions)

D Stanley
  • 149,601
  • 11
  • 178
  • 240
6

This is expected behavior.

A double can't represent every number exactly. This has nothing to do with the string conversion.

You can check it yourself:

Console.WriteLine(93389.429999999993);

This will print 93389.43.

The following also shows this:

Console.WriteLine(93389.429999999993 == 93389.43);

This prints True.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
4

Keep in mind that there are two conversions going on here. First you're converting the string to a double, and then you're converting that double back into a string to display it.

You also need to consider that a double doesn't have infinite precision; depending on the string, some data may be lost due to the fact that a double doesn't have the capacity to store it.

When converting to a double it's not going to "round" any more than it has to. It will create the double that is closest to the number provided, given the capabilities of a double. When converting that double to a string it's much more likely that some information isn't kept.

Servy
  • 202,030
  • 26
  • 332
  • 449
3

See the following (in particular the first part of Michael Borgwardt's answer):

decimal vs double! - Which one should I use and when?

A double will not always keep the precision depending on the number you are trying to convert

If you need to be precise you will need to use decimal

Community
  • 1
  • 1
NinjaNye
  • 7,046
  • 1
  • 32
  • 46
0

This is a limit on the precision that a double can store. You can see this yourself by trying to convert 3389.429999999993 instead.

Bobson
  • 13,498
  • 5
  • 55
  • 80
0

The double type has a finite precision of 64 bits, so a rounding error occurs when the real number is stored in the numberAsDouble variable.

A solution that would work for your example is to use the decimal type instead, which has 128 bit precision. However, the same problem arises with a smaller difference.

For arbitrary large numbers, the System.Numerics.BigInteger object from the .NET Framework 4.0 supports arbitrary precision for integers. However you will need a 3rd party library to use arbitrary large real numbers.

J-Mik
  • 896
  • 7
  • 8
  • I'm not sure what you mean by number, but in more details (using google) the decimal precision sign=1 bit, mantissa=96 bit, exponent=29 bit? I haven't read anything clear on the exponent, and the total # of bits used is 128 bit. – J-Mik Jan 15 '13 at 19:59
0

You could truncate the decimal places to the amount of digits you need, not exceeding double precision.

For instance, this will truncate to 5 decimal places, getting 93389.42999. Just replace 100000 for the needed value

string number = "93389.429999999993";
decimal numberAsDecimal = Convert.ToDecimal(number);
var numberAsDouble = ((double)((long)(numberAsDecimal * 100000.0m))) / 100000.0;
Esteban Elverdin
  • 3,552
  • 1
  • 17
  • 21