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.

7
  • IIRC, it is parsing number correctly, however, it is being displayed as a rounded value when printed. Insert a breakpoint and confirm this. I may be wrong, though, hence the comment. Commented Jan 15, 2013 at 17:47
  • Please see if previous answers help - stackoverflow.com/questions/tagged/… ... Commented Jan 15, 2013 at 17:48
  • Why do you need it as a double?
    – D Stanley
    Commented Jan 15, 2013 at 17:55
  • @DStanley i need to pass the value as double to a library to make other calculations Commented Jan 15, 2013 at 17:56
  • 2
    @GiorgosManoltzas - That library isn't going to be able to be any more precise with a double than your code will be.
    – Bobson
    Commented Jan 15, 2013 at 18:00

7 Answers 7

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)

2
  • thanks for helping - i need to pass the exact value a double to a library to make calculations based on the value Commented Jan 15, 2013 at 17:58
  • @Chux - You win; Congrats! Commented Jul 9, 2015 at 20:52
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.

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.

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

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.

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.

1
  • 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
    Commented Jan 15, 2013 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;

Not the answer you're looking for? Browse other questions tagged or ask your own question.