Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 相乘时的十进制精度_C#_.net_Decimal_Precision - Fatal编程技术网

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