С# Преобразование объекта в десятичный
Я пытаюсь преобразовать объект со значением 0.39999999999999997
в десятичную переменную без потери точности.
object d = 0.39999999999999997;
Я пробовал следующие методы.
decimal val1 = Convert.ToDecimal(d); // val1 = 0.4
object val2 = Convert.ChangeType(d, Type.GetType("System.Decimal")); // val2 = 0.4
decimal val3 = decimal.Parse(d.ToString()); // val3 = 0.4
decimal val4 = (Decimal) d; // val4 = 0.4
Я знаю, что это не проблема с типом десятичных данных, который не может сохранить это значение, как показано ниже.
decimal val5 = 0.39999999999999997m; // val5 = 0.39999999999999997;
Как преобразовать этот объект в десятичный без потери точности?
Я использую .NET Framework 3.5, если это имеет значение.
Ответы
Ответ 1
Я думаю, что это код, который вы ищете:
object d = 0.39999999999999997;
//Unbox value
double doubleVal = (double)d;
//Convert to string. R format specifier gives a string that can round-trip to an identical number.
//Without R ToString() result would be doubleAsString = "0.4"
string doubleAsString = doubleVal.ToString("R");
//Now that you have doubleAsString = "0.39999999999999997" parse it!
decimal decimalVal = decimal.Parse(doubleAsString);
Ответ 2
Для этого вам нужно будет назначить его аналогичным образом
object d = 0.39999999999999997M;
У объекта нет возможности поддерживать точность, если вы ее не заставляете. (Если это не настоящий код, вам нужно будет показать, как его назначили)
Только тогда что-то вроде этого будет работать decimal dec = Convert.ToDecimal(d);
Ответ 3
Когда вы читаете данные из базы данных (как вы отметили в одном из комментариев, IMO, вы должны добавить это в свой вопрос), я думаю, что это ужасная идея разрешить преобразование в двойное и обратное во время чтения из базы данных, потому что вы будет потерять точность [вероятно, он хранится как фиксированная точка или в числовой системе, которая может представлять десятичные числа].
Я думаю, что вы должны приложить некоторые усилия, чтобы прочитать сохраненные значения непосредственно в виде десятичных знаков (отредактируйте свою схему или что-то в этом роде), или если это невозможно, прочитайте их как строки и используйте Decimal.Parse() для получения фактических значений.
Фактически, ваш номер 0.39999999999999997 имеет 17 знаков после запятой, поэтому его нельзя сохранить как дважды безопасно.
P.S. Там отличная статья относительно .net. Партии и округление, написанные Джоном Скитом.
Ответ 4
string val = "0.39999999999999997");
decimal d = decimal.Parse(val,
System.Globalization.NumberStyles.AllowDecimalPoint);//0.39999999999999997
Ответ 5
Decimal d = new Decimal(d);
если d является двойным, то согласно документации MSDN это должно сохранять точность.
Этот конструктор округляет значение до 15 значащих цифр с округлением до ближайшего. Это делается, даже если число содержит более 15 цифр, а менее значимые цифры - равны нулю.
Ответ 6
на этой странице http://msdn.microsoft.com/en-us/library/364x0z75(v=vs.80).aspx он написал: "Без суффикса m число рассматривается как двойное"
И этот код
object o = 0.39999999999999997;
Console.WriteLine(o.GetType());
отображается System.Double
в то время как этот
object o = 0.39999999999999997m;
Console.WriteLine(o.GetType());
отображается System.Decimal
Таким образом, вы просто теряете свою точность без суффикса m.
Ответ 7
объект d = 0,399999999999999999999999997M;
будет работать на вас.
Ответ 8
Серьезно все, что вам нужно сделать, это что-то вроде этого...
object d = 0.39999999999999997;
decimal result;
decimal.TryParse(d.ToString(), out result);
return result;