调整小数精度,.net

问题描述 投票:0回答:8

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?
.net decimal precision
8个回答
59
投票

.NET 1.1 中引入了这样的保留尾随零,以更严格地符合 ECMA CLI 规范。

MSDN 上有一些关于此的信息,例如这里

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

  • Math.Round(或 Ceiling、Floor 等)降低精度(b 来自 c)

  • 乘以 1.000...(您想要的小数位数)以提高精度 - 例如a 乘以 1.0M 得到 b。


19
投票

您只是看到完全相同数据的不同表示形式。

decimal
的精度将缩放至所需的大小(在合理范围内)。

来自

System.Decimal

十进制数是浮点数 由符号、a 组成的值 数值,其中每个数字 值范围从 0 到 9,并且 a 比例因子表示 浮动小数点的位置 将积分和 数值的小数部分。

十进制的二进制表示 值由 1 位符号、 96 位整数和缩放 用于划分 96 位的因子 整数并指定它的哪一部分 是小数。缩放比例 因子隐式是数字 10, 提升至 0 范围内的指数 到 28。因此,二进制 Decimal 值的表示形式是 形式为 ((-296 至 296) / 10(0 至 28)),其中 -296-1 等于 MinValue,且 296-1 等于 最大值。

缩放因子还保留任何 十进制数中的尾随零。 尾随零不影响 十进制数的值 算术或比较运算。 然而,尾随零可以是 由 ToString 方法显示,如果 应用适当的格式字符串。


9
投票

8
投票

我发现我可以通过乘以或除以一个奇特的 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;

6
投票

很容易将 SQL Server 中的

decimal
与 .NET 中的
decimal
混淆;他们完全不同。

SQL Server

decimal
是一个定点数,当定义列或变量时,其精度和小数位数是固定的。

A .NET

decimal
是浮点数,类似于
float
double
(区别在于
decimal
准确保留十进制数字,而
float
double
准确保留二进制数字)。尝试控制 .NET
decimal
的精度是没有意义的,因为无论是否存在填充零,所有计算都会产生相同的结果。


2
投票

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

ToString()

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

或者,如果您想要精确数量的尾随零,例如 5,请先使用 Normalize(),然后乘以 1.00000m。


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


0
投票

public static decimal SetScale(this decimal input, int scale) { if (scale < 0) throw new ArgumentOutOfRangeException(nameof(scale)); if (input.Scale == scale) return input; //normalize input /= 1.000000000000000000000000000000000m; var scaleToadd = scale - input.Scale; for(int i = 0; i < scaleToadd; i++) { input *= 1.0M; } return input; }

并在 getter 上使用它来强制尾随零,例如作为 

:solution for Blazor to show trailing zeros private decimal price; public decimal Price { get => price.SetScale(2); set => price = value; }

© www.soinside.com 2019 - 2024. All rights reserved.