调整小数精度,.net

时间:2009-07-15 17:24:52

标签: .net decimal precision

C#中的这些行

decimal a = 2m;
decimal b = 2.0m;
decimal c = 2.00000000m;
decimal d = 2.000000000000000000000000000m;

Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);

生成此输出:

2
2.0
2.00000000
2.000000000000000000000000000

所以我可以看到从文字中创建一个十进制变量允许我控制精度。

  • 我可以在不使用文字的情况下调整十进制变量的精度吗?
  • 如何从a创建b?如何从c创建b?

7 个答案:

答案 0 :(得分:49)

为了更严格地遵守ECMA CLI规范,在.NET 1.1中引入了保留这样的尾随零。

在MSDN上有一些关于此的信息,例如: here

您可以按如下方式调整精度:

  • Math.Round(或天花板,地板等)降低精度(b来自c)

  • 乘以1.000 ...(用你想要的小数位数)来提高精度 - 例如乘以1.0M从a获得b。

答案 1 :(得分:18)

您只是看到完全相同数据的不同表示。 decimal的精度将缩放到需要的大小(在合理范围内)。

来自System.Decimal

  

十进制数是一个浮点数   由符号组成的值,a   数字值中的每个数字   值的范围是0到9, a   缩放因子,表示   浮动小数点的位置   分隔积分和   数值的小数部分。

     

十进制的二进制表示   值由1位符号组成   96位整数,以及缩放   用于分割96位的因子   整数并指定它的哪个部分   是小数部分。缩放   因素是隐含的数字10,   提升到0的指数   到28.因此,二进制   十进制值的表示是   形式,(( - 2 96 至2 96 )/ 10 (0至   28)),其中-2 96 -1等于   MinValue和2 96 -1等于   MaxValue的。

     

缩放系数也会保留任何缩放系数   以十进制数表示尾随零。   尾随零不会影响   一个十进制数的值   算术或比较操作。   但是,尾随零可以   如果一个ToString方法透露   应用适当的格式字符串。

答案 2 :(得分:6)

答案 3 :(得分:5)

我发现我可以通过乘以或除以花式1来“篡改”刻度。

decimal a = 2m;
decimal c = 2.00000000m;
decimal PreciseOne = 1.000000000000000000000000000000m;
  //add maximum trailing zeros to a
decimal x = a * PreciseOne;
  //remove all trailing zeros from c
decimal y = c / PreciseOne;

我可以制作足够精确的1来改变已知尺寸的比例因子。

decimal scaleFactorBase = 1.0m;
decimal scaleFactor = 1m;
int scaleFactorSize = 3;

for (int i = 0; i < scaleFactorSize; i++)
{
  scaleFactor *= scaleFactorBase;
}

decimal z = a * scaleFactor;

答案 4 :(得分:5)

将SQL Server中的decimal与.NET中的decimal混淆是很诱人的;他们是完全不同的。

SQL Server decimal是一个定点数,在定义列或变量时,其精度和比例是固定的。

.NET decimal是一个浮点数,如floatdouble(不同之处在于decimal准确保留十进制数字,而floatdouble准确保留二进制数字)。试图控制.NET decimal的精度是没有意义的,因为无论是否存在填充零,所有计算都会产生相同的结果。

答案 5 :(得分:1)

问题是 - 你真的需要十进制中的精确存储,而不是仅仅将十进制显示到所需的精度。 大多数应用程序在内部知道他们想要的精确度并显示到该精确度。例如,即使用户在帐户包中输入100的发票,它仍然使用val.ToString(“n2”)之类的内容输出为100.00。

  

如何从a创建b?如何从c创建b?

c到b是可能的。

Console.WriteLine(Math.Round(2.00000000m, 1)) 

产生2.0

a到b很棘手,因为引入精度的概念与数学有点陌生。

我猜一个可怕的黑客可能是一次往返。

decimal b = Decimal.Parse(a.ToString("#.0"));
Console.WriteLine(b);

产生2.0

答案 6 :(得分:1)

这将从小数中删除所有尾随零,然后您可以使用ToString()

public static class DecimalExtensions
{
    public static Decimal Normalize(this Decimal value)
    {
        return value / 1.000000000000000000000000000000000m;
    }
}

或者,如果你想要一个确切数量的尾随零,比如说5,首先是Normalize()然后再乘以1.00000m。