Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert string to double with 2 digit after decimal separator

All began with these simple lines of code:

string s = "16.9";
double d = Convert.ToDouble(s);
d*=100;

The result should be 1690.0, but it's not. d is equal to 1689.9999999999998. All I want to do is to round a double to value with 2 digit after decimal separator. Here is my function.

private double RoundFloat(double Value)
{
    float sign = (Value < 0) ? -0.01f : 0.01f;

    if (Math.Abs(Value) < 0.00001) Value = 0;

    string SVal = Value.ToString();
    string DecimalSeparator = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator;
    int i = SVal.IndexOf(DecimalSeparator);
    if (i > 0)
    {
        int SRnd;
        try
        {
            // вземи втората цифра след десетичния разделител
            SRnd = Convert.ToInt32(SVal.Substring(i + 3, 1));
        }
        catch
        {
            SRnd = 0;
        }

        if (SVal.Length > i + 3)
            SVal = SVal.Substring(0, i + 3);
        //SVal += "00001";

        try
        {
            double result = (SRnd >= 5) ? Convert.ToDouble(SVal) + sign : Convert.ToDouble(SVal);
            //result = Math.Round(result, 2);
            return result; 
        }
        catch
        {
            return 0;
        }
    }
    else
    {
        return Value;
    }

But again the same problem, converting from string to double is not working as I want. A workaround to this problem is to concatenate "00001" to the string and then use the Math.Round function (commented in the example above).

This double value multiplied to 100 (as integer) is send to a device (cash register) and this values must be correct.

I am using VS2005 + .NET CF 2.0

Is there another more "elegant" solution, I am not happy with this one.

like image 615
Stanislav Stoyanov Avatar asked Oct 19 '09 10:10

Stanislav Stoyanov


3 Answers

Doubles can't exactly represent 16.9. I suggest you convert it to decimal instead:

string s = "16.9";
decimal m = Decimal.Parse(s) * 100;

double d = (double)m;

You might just want to keep using the decimal instead of the double, since you say you'll be using it for monetary purposes. Remember that decimal is intended to exactly represent decimal numbers that fit in its precision, while double will only exactly represent binary numbers that do.

like image 78
Joren Avatar answered Sep 22 '22 10:09

Joren


Math.Round(number, 1)

Edit I got the wrong question - the rounding problems are inherent to a floating point type (float, double). You should use decimal for this.

like image 21
rslite Avatar answered Sep 21 '22 10:09

rslite


The best solution for not going be crazy is: string s = "16.9";

For ,/. double d = Convert.ToDouble(s.Replace(',','.'),System.Globalization.CultureInfo.InvariantCulture);

For rounding: Convert.ToDouble((d).ToString("F2"));

like image 33
feliciuccio Avatar answered Sep 22 '22 10:09

feliciuccio