C# 银行家的舍入误差

发布于 2024-09-24 17:56:18 字数 214 浏览 3 评论 0原文

double a = 18.565
return Math.Round(a,2)

..返回 18.57。
对于其他每个数字,我尝试了银行家的四舍五入,结果按预期工作,例如 Math.Round(2.565,2) 返回 2.56。

知道为什么以及何时发生这种情况吗? 这是错误还是我遗漏了有关银行家四舍五入的信息?

谢谢..

double a = 18.565
return Math.Round(a,2)

..returns 18.57.
For every other number I tried banker's rounding worked as expected, for example Math.Round(2.565,2) returned 2.56.

Any clue why and when that happens?
Is it error or am I missing something about banker's rounding?

Thanks..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

自此以后,行同陌路 2024-10-01 17:56:18

正如Matthew所说,18.565无法准确表示。实际使用的值是18.565000000000001278976924368180334568023681640625(使用DoubleConverter找到),显然超过了一半-方式。现在我有一种隐隐的感觉,有时 Math.Round 会考虑一个实际上超出中点的值,但它是尽可能接近可以准确表示的中点,就像恰好该点一样。但是,我还没有看到任何描述其应用情况的文档,并且显然在本例中没有发生这种情况。我不想依赖它。

当然,即使四舍五入的值也不完全是 18.57。实际上是18.57000000000000028421709430404007434844970703125。

从根本上讲,如果您真的非常关心准确表示十进制值,那么您应该使用decimal。这不仅仅是在 Math.Round 方面 - 它涉及处理浮点值的各个方面。

当然,这确实Math.Round提供了正确的值:

decimal m = 18.565m;
Console.WriteLine(Math.Round(m, 2)); // Prints 18.56

As Matthew said, 18.565 can't be accurately represented. The actual value used is 18.565000000000001278976924368180334568023681640625 (found using DoubleConverter), which is clearly beyond half-way. Now I've a sneaking feeling that sometimes Math.Round will consider a value which is actually beyond the half-way point, but which is as close to the half-way point as can be accurately represented, as being exactly at that point. However, I haven't seen any documentation describing the situations in which that's applied, and clearly it's not happening in this case. I wouldn't want to rely on it.

Even the rounded value isn't exactly 18.57 of course. It's actually 18.57000000000000028421709430404007434844970703125.

Fundamentally, if you really, really care about representing decimal values accurately, you should be using decimal. That's not just in terms of Math.Round - it goes to every aspect of handling floating point values.

That does give the right value for Math.Round, of course:

decimal m = 18.565m;
Console.WriteLine(Math.Round(m, 2)); // Prints 18.56
几味少女 2024-10-01 17:56:18

18.565 不能精确地表示为双精度数。因此,二进制表示稍高,因此向上舍入。如果使用decimal:

decimal a = 18.565m;
return Math.Round(a,2)

可以精确表示,就不会有这个问题。

18.565 can not be exactly represented as a double. Thus, the binary representation is slightly higher, so it rounds up. If you use decimal:

decimal a = 18.565m;
return Math.Round(a,2)

it can be exactly represented, and you won't have this issue.

橘寄 2024-10-01 17:56:18

我的猜测是 FP 表示意味着它实际上不是尾随 5;而是尾随 5。 FP的危险!

不过,这工作得很好:

        decimal a = 18.565M; // <===== decimal
        var s = Math.Round(a, 2);

My guess is that the FP representation means it isn't actually a trailing 5; the dangers of FP!

This works fine, though:

        decimal a = 18.565M; // <===== decimal
        var s = Math.Round(a, 2);
凉风有信 2024-10-01 17:56:18

Double 是一个浮点值,所以如果你将其写为 18.565,它实际上在内存中的值类似于 18.56500000000000000000000000000000001,因此它大于中点。

Double is a floating point value, so maybe if you write it as 18.565, it is actually in memory something like 18.56500000000000000000000000000000001, and hence it is more than the midpoint.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文