可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to convert an object with the value 0.39999999999999997 to a decimal variable without losing the precision.
object d = 0.39999999999999997;
I've tried the following methods.
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
I know the this is not a problem with the decimal data type not being able to store this value as illustrated below.
decimal val5 = 0.39999999999999997m; // val5 = 0.39999999999999997;
How do I convert this object to decimal without losing the precision?
I'm using .NET Framework 3.5 if that matters.
回答1:
I think this is the code you looking for:
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:
For this to work you will need to assign it similarly
object d = 0.39999999999999997M;
There is no way for the object to maintain the precision unless you force it to. (If this is not the actual code, you will need to show as how its assigned)
Only then would something like this would work decimal dec = Convert.ToDecimal(d);
回答3:
As you are reading data from database(as you noted in one of the comments, IMO you should have added that in your question) I think it's a terrible idea to allow converting to double and back while reading from database, because you will lose precision [likely it's stored as fixed point or in a number system that can represent decimals]. I think that you must put some effort to read the stored values directly as decimals(edit your schema or something like that), or if it's not possible, then read them as strings, and use Decimal.Parse() to get actual values.
Actually your number 0.39999999999999997 has 17 decimal places hence it can't be stored as double safely.
P.S. There's a great article regarding .net Doubles and rounding written by Jon Skeet.
回答4:
Decimal d = new Decimal(d);
if d is a double, then according to the documentation MSDN this should keep the precision.
This constructor rounds value to 15 significant digits using rounding to nearest. This is done even if the number has more than 15 digits and the less significant digits are zero.
回答5:
on this page http://msdn.microsoft.com/en-us/library/364x0z75(v=vs.80).aspx it's written "Without the suffix m, the number is treated as a double"
And this code
object o = 0.39999999999999997; Console.WriteLine(o.GetType());
shows up System.Double
while this one
object o = 0.39999999999999997m; Console.WriteLine(o.GetType());
shows up System.Decimal
So you're just losing your precision without the suffix m.
回答6:
string val = "0.39999999999999997"); decimal d = decimal.Parse(val, System.Globalization.NumberStyles.AllowDecimalPoint);//0.39999999999999997
回答7:
object d = 0.399999999999999999999999997M; would work you.
回答8:
Seriously all you have to do is something like this...
object d = 0.39999999999999997; decimal result; decimal.TryParse(d.ToString(), out result); return result;