use*_*360 34 c# decimal multiplication
在C#中乘以十进制值时,我注意到一种奇怪的行为.考虑以下乘法运算:
1.1111111111111111111111111111m * 1m = 1.1111111111111111111111111111 // OK
1.1111111111111111111111111111m * 2m = 2.2222222222222222222222222222 // OK
1.1111111111111111111111111111m * 3m = 3.3333333333333333333333333333 // OK
1.1111111111111111111111111111m * 4m = 4.4444444444444444444444444444 // OK
1.1111111111111111111111111111m * 5m = 5.5555555555555555555555555555 // OK
1.1111111111111111111111111111m * 6m = 6.6666666666666666666666666666 // OK
1.1111111111111111111111111111m * 7m = 7.7777777777777777777777777777 // OK
1.1111111111111111111111111111m * 8m = 8.888888888888888888888888889 // Why not 8.8888888888888888888888888888 ?
1.1111111111111111111111111111m * 9m = 10.000000000000000000000000000 // Why not 9.9999999999999999999999999999 ?
Run Code Online (Sandbox Code Playgroud)
我无法理解的是上述最后两个案例.怎么可能?
Jon*_*eet 73
decimal存储28或29位有效数字(96位).基本上尾数在 - /+ 79,228,162,514,264,337,593,543,950,335范围内.
这意味着高达约7.9 ....你可以准确地得到29位有效数字 - 但高于你不能.这就是8和9都出错的原因,但不是早期的价值观.一般来说,你应该只依赖 28位有效数字,以避免像这样的奇怪情况.
将原始输入减少到28位有效数字后,您将获得预期的输出:
using System;
class Test
{
static void Main()
{
var input = 1.111111111111111111111111111m;
for (int i = 1; i < 10; i++)
{
decimal output = input * (decimal) i;
Console.WriteLine(output);
}
}
}
Run Code Online (Sandbox Code Playgroud)