Преобразовать строку в двойную с 2 цифрами после десятичного разделителя

Все началось с этих простых строк кода:

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

Результат должен быть 1690.0, но это не так. d равно 1689,9999999999998. Все, что я хочу сделать, это округлить двойное значение до значения с 2 цифрами после десятичного разделителя. Вот моя функция.

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;
    }

Но снова та же проблема, преобразование из строки в двойную не работает, как я хочу. Обходной путь для этой проблемы — объединить «00001» со строкой, а затем использовать функцию Math.Round (закомментирована в приведенном выше примере).

Это двойное значение, умноженное на 100 (как целое число), отправляется на устройство (кассовый аппарат), и эти значения должны быть правильными.

Я использую VS2005 + .NET CF 2.0.

Есть ли другое более «элегантное» решение, я не доволен этим.


person Stanislav Stoyanov    schedule 19.10.2009    source источник
comment
Еще один день, еще один человек терпит неудачу с плавающей запятой :(   -  person leppie    schedule 19.10.2009
comment
Это тоже похоже на дублирующий вопрос. Не уверен, что помню, где я это видел.   -  person    schedule 19.10.2009
comment
Это довольно распространенная вещь, поэтому на этом сайте обязательно будет несколько дубликатов. Но я думаю, что найти их сложнее, чем просто ответить, так что хорошо. :)   -  person Joren    schedule 19.10.2009


Ответы (3)


Двойники не могут точно представлять 16,9. Я предлагаю вместо этого преобразовать его в decimal:

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

double d = (double)m;

Вы можете просто продолжать использовать decimal вместо double, так как вы говорите, что будете использовать его в денежных целях. Помните, что decimal предназначено для точного представления десятичных чисел, которые соответствуют его точности, в то время как double будет точно представлять только двоичные числа, которые подходят.

person Joren    schedule 19.10.2009

Math.Round(number, 1)

Изменить Я задал неправильный вопрос - проблемы с округлением свойственны типам с плавающей запятой (float, double). Вы должны использовать десятичную дробь для этого.

person rslite    schedule 19.10.2009

Лучшее решение, чтобы не сойти с ума: string s = "16.9";

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

Для округления: Convert.ToDouble((d).ToString("F2"));

person feliciuccio    schedule 14.05.2013