【发布时间】:2020-09-30 14:26:50
【问题描述】:
我正在为我的同事设置一个关于 C# 在 Math.Round 函数中使用的银行家舍入方法的小测验。但是在 repl.it 中准备问题时,我得到了一个我认为很奇怪的结果。起初我使用的是一个数组,但我设法将其归结为这个 sn-p 以找到一个小的复制场景:
class MainClass {
public static void Main (string[] args) {
double x = 10.5;
System.Console.WriteLine(format: "Math.Round({0}) = {1}",
arg0: x,
arg1: System.Math.Round(x));
const double y = 10.5;
System.Console.WriteLine(format: "Math.Round({0}) = {1}",
arg0: y,
arg1: System.Math.Round(y));
}
}
这会产生以下输出:
Math.Round(10.5) = 10
Math.Round(10.5) = 11
(我也用decimal 数字尝试过,这并没有导致计算方法之间的任何差异:根据银行家的四舍五入规则,两者都导致了10。)
现在,我猜这可能与预编译的 const double 版本有关,但我希望 - 我不确定这是否合理 - 预编译版本使用相同的舍入规则和/或(我不确定确切的原因是什么)遭受完全相同的舍入误差 - 实际上,我期望它执行完全相同的计算,只是在不同的时间。
很难找到有关此行为的更多信息,部分原因是我不确定我是否遇到了 Math.Round 中的错误(显然,这也有一些问题)或者是什么与consts 允许的预编译有关,但我猜是后者 - 搜索“c# const different result”之类的东西并没有立即有用。
所以我的问题是,谁能解释这个输出:“这只发生在编译器在平台 X 上运行,然后程序因为 Z 在平台 Y 上运行时才会发生这种情况”?
(编辑:抱歉,忘记发布 repl.it 链接。Here 是!)
【问题讨论】:
-
@JohnathanBarclay 他说他在 repl.it 中运行它,在那里可以重现。
-
repl.it 在撰写本文时在单声道 6.10.0.104 下运行
-
Can't reproduce 在小提琴中。
-
@MatthewWatson 看起来像。在这里测试:jdoodle.com/compile-c-sharp-online 使用 Mono 5.10.1,两者都是 10。Mono 6.0 产生 10 和 11。
-
真是奇怪的错误。
10.5在 IEEE 754 中完全可以表示,没有四舍五入的问题,所以我们不能把它归咎于此。