C#将对象转换为Decimal

时间:2011-07-27 07:12:00

标签: c# .net types precision

我正在尝试将值为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。

8 个答案:

答案 0 :(得分:10)

我认为这是您要寻找的代码:

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

答案 1 :(得分:4)

为此,您需要以类似方式分配

object d = 0.39999999999999997M;

除非你强制它,否则对象无法保持精度。 (如果这不是实际代码,则需要显示其分配方式)

只有这样,这样的事情才能起作用decimal dec = Convert.ToDecimal(d);

答案 2 :(得分:1)

当您从数据库中读取数据时(正如您在其中一条评论中所述,IMO您应该在您的问题中添加)我认为在从数据库读取时允许转换为double和back是一个糟糕的主意,因为您将丢失精度[可能它存储为固定点或可以表示小数的数字系统]。 我认为你必须付出一些努力直接以小数形式读取存储的值(编辑你的模式或类似的东西),或者如果它不可能,那么将它们作为字符串读取,并使用Decimal.Parse()来获取实际值。

实际上您的号码0.39999999999999997有17个小数位,因此不能安全地存储为双倍。

P.S。关于.net双打和舍入由Jon Skeet撰写的a great article

答案 3 :(得分:0)

string val = "0.39999999999999997");
decimal d = decimal.Parse(val,
    System.Globalization.NumberStyles.AllowDecimalPoint);//0.39999999999999997

答案 4 :(得分:0)

Decimal d = new Decimal(d);

如果d是double,那么根据文档MSDN,这应该保持精度。

  

此构造函数使用舍入到最接近的值将值舍入为15位有效数字。即使数字超过15位且较低有效数字为零,也会这样做。

答案 5 :(得分:0)

在此页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的情况下失去你的精度。

答案 6 :(得分:0)

对象d = 0.39999999999999999999999999997M; 会工作的。

答案 7 :(得分:0)

说真的,你所要做的就是这样......

function isAccount(accountName) {
      UserService.getAuthenticatedUser()
         .then(function (response) {
             var userDetails = response.data;
             UserService.getAccountTypeData(idUser)
                .then(function (response) {
                    var userDetails = response.data;
                    return  userDetails;
                });
         });
}