C#中的float/double Math.Round

Yao*_*ing 18 c# double rounding

float ff = (float)31.15;

double dd = 31.15;

var frst = Math.Round(ff, 1, MidpointRounding.AwayFromZero);

var drst = Math.Round(dd, 1, MidpointRounding.AwayFromZero);
Run Code Online (Sandbox Code Playgroud)

第一次:31.1

第一次:31.2

有人可以解释原因吗?

Dmi*_*nko 27

嗯,Math.Round想要double,不是float,这就是原因

Math.Round(ff, 1, MidpointRounding.AwayFromZero);
Run Code Online (Sandbox Code Playgroud)

等于

Math.Round((double)ff, 1, MidpointRounding.AwayFromZero);
Run Code Online (Sandbox Code Playgroud)

如果我们检查(double)ff价值

Console.Write(((double)ff).ToString("R"));
Run Code Online (Sandbox Code Playgroud)

我们将看到圆了错误的行动

31.149999618530273
Run Code Online (Sandbox Code Playgroud)

最后,Math.Round(31.149999618530273, 1, MidpointRounding.AwayFromZero) == 31.1正如所料

  • @Gonzalo Lorieto:`double`是*binary*和`0.15 == 15/100 = 3/20'是二进制表示的*周期分数*. (7认同)

Ben*_*Ben 12

在浮点数中,所有数字在内部表示为分数,其中分母是2的幂.

(这与十进制实际上如何使用10分之幂的分数的方式类似.所以31.15只是一种写分数的方法 3115/100)

在浮点数中,31.15必须在内部表示为二进制数.最接近的二进制分数是:1111.1001001100110011001100110011001100110011001100110011001100...repeating

1100重复(反复永远)等的数量将取决于它是否被存储在双或浮法被截断.在一个浮点数中它被截断为24位数,并在一个double到53位.

Exact:  1111.100100110011001100110011001100110011001100110011001100110011001100...forever
Float:  1111.10010011001100110011
Double: 1111.1001001100110011001100110011001100110011001100110
Run Code Online (Sandbox Code Playgroud)

因此,您可以看到此数字转换为的double实际上比它转换为的float稍大.所以很明显,它不一定会舍入到相同的数字,因为它与开头的数字不同.


归档时间:

查看次数:

1576 次

最近记录:

6 年,6 月 前