C# 相乘时的十进制精度
给定两个类似的值:C# 相乘时的十进制精度,c#,.net,decimal,precision,C#,.net,Decimal,Precision,给定两个类似的值: decimal a = 0.15m; decimal b = 0.85m; 如果a+b始终为1.0m,则两个值仅指定为小数点后2位,且两个值均=0.0m,十进制存储为表示十进制位置的数字10的符号、整数和整数指数。只要数字的整数部分(例如105.99中的105)不够大,那么a+b将始终等于1。方程(x*a)+(x*b)的结果总是有四位小数的正确值 与float和double不同,精度不会损失到数据类型的大小(128位) 从MSDN: Decimal value类型表示从 正
decimal a = 0.15m;
decimal b = 0.85m;
如果
a+b
始终为1.0m
,则两个值仅指定为小数点后2位,且两个值均=0.0m
,十进制存储为表示十进制位置的数字10的符号、整数和整数指数。只要数字的整数部分(例如105.99中的105)不够大,那么a+b将始终等于1。方程(x*a)+(x*b)的结果总是有四位小数的正确值
与float和double不同,精度不会损失到数据类型的大小(128位)
从MSDN:
Decimal value类型表示从
正极79228162514264337593543950335至负极
79,228,162,514,264,337,593,543,950,335. 十进制值类型为
适用于需要大量数据的财务计算
有效整数和小数位数,无舍入误差。
十进制类型并不排除四舍五入的需要。相反,它
最大限度地减少舍入误差。例如,下面的代码
生成的结果为0.99999999999999999999,而不是1
CLR中十进制
的最大精度为29位有效数字。当您使用这种精度时,您实际上是在谈论近似值,尤其是当您进行乘法运算时,因为这需要CLR必须能够处理的中间结果(另请参见)
如果x有两个有效数字,比如a有20个有效数字,那么x*a的最小精度已经是22位,中间结果可能需要更多的精度
如果x总是只有2个有效数字,并且可以将a和b中的有效数字保持在足够低的水平(比如,22个数字——非常好,可能离27足够远,可以处理舍入错误),那么我认为(x*a)+(x*b)应该是一个非常精确的计算
最后,a+b是否总是占1.0m与a和b的个别精度无关。指定为无限小数位是什么意思?是否0.85m
与0.850000000000000m
不同?@Rotem二进制表示不同;我不确定当你倍增的时候,它是否会导致行为上的差异。编辑:-尾随的零不会影响算术或比较运算中十进制数的值
@Rawling引用MSDN声明的答案:CubeSchrauber你看过吗?检查底部1
和1.0000000000000000000000
的示例输出。小数不像双精度/浮点数那样存储,而是使用基数10,这会产生巨大的差异。@CubeSchrauber你是认真的吗?!当然,它是以二进制形式存储的,因为所有内容都是(顺便说一句,FF
是十六进制的,而不是二进制的)。这并没有改变浮点数/双精度和小数在内部的表示方式。浮点数用(-1)^s*m*2^e
表示;这就是为什么它可以精确地表示0.5(1*2^-1
),而不是0.3。另一方面,小数以10为基数,使用(-1)^s*m*10^e
,因此如果m和e足够精确,我们可以精确地表示所有小数,包括0.3(3*10^-1
)。继续读下去。
decimal x = 105.99m;
decimal total = (x * a) + (x * b);
decimal dividend = Decimal.One;
decimal divisor = 3;
// The following displays 0.9999999999999999999999999999 to the console
Console.WriteLine(dividend/divisor * divisor);