c# - C# 计算在 const 和 variable locals 之间有什么不同?
问题描述
我正在为我的同事设置一个关于 C# 在Math.Round
函数中使用的银行家舍入方法的流行测验。但是在 repl.it 中准备问题时,我得到了一个我认为很奇怪的结果。起初我正在使用一个数组,但我设法将其归结为这个片段以找到一个小的复制场景:
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
预编译的版本有关,但我希望 - 我不确定这是合理的 - 预编译版本使用相同的舍入规则和/或(I'我不确定确切的原因是什么)遭受完全相同的舍入误差 - 实际上,我希望它执行完全相同的计算,只是在不同的时间。
很难找到有关此行为的更多信息,部分原因是我不确定我是否遇到了错误Math.Round
(显然也有一些问题)或与预编译相关const
的问题允许,但我猜是后者——搜索“c# const different result”之类的东西没有给我任何立即有用的东西。
所以我的问题是,任何人都可以用“只有当编译器在平台 X 上运行并且程序然后因为 Z 在平台 Y 上运行时才会发生这种情况”来解释这个输出?
(编辑:抱歉,忘记发布 repl.it 链接。在这里!)
解决方案
我不确定这是否是单声道编译器的错误,但我在这里遇到了类似的问题,以及贡献者在此处所做的代码更改。
我的猜测是 Round 函数将测试中的小数位更改为值X,但使用常量Y时,原始值不会改变。
以下是一种可能的解决方法:
double x = 10.5;
const double y = 10.5;
System.Console.WriteLine(format: "Math.Round({0}) = {1}",
arg0: x,
arg1: System.Math.Round(x, 0, MidpointRounding.AwayFromZero));
// 11
System.Console.WriteLine(format: "Math.Round({0}) = {1}",
arg0: y,
arg1: System.Math.Round(y, 0 , MidpointRounding.AwayFromZero));
// 11
System.Console.WriteLine(format: "Math.Round({0}) = {1}",
arg0: x,
arg1: System.Math.Round(y, 0 , MidpointRounding.ToEven));
// 10
System.Console.WriteLine(format: "Math.Round({0}) = {1}",
arg0: y,
arg1: System.Math.Round(y, 0 , MidpointRounding.ToEven));
// 10
我能够在 Windows 10 上的 x_86 和 x_64 中的 .NET、.NET Core 3.0 中正确执行 Math.Round。
也许将单声道 github 报告为一个问题。如果这样做,您可以在 Repl.it 的命令行窗口中使用以下命令获取系统和编译器信息
系统信息:uname -a
Linux 52d579a3a5fc 5.4.0-1019-gcp #19-Ubuntu SMP 2020 年 6 月 23 日星期二 15:46:40 UTC x86_64 x86_64 x86_64 GNU/Linux
编译器版本:mono --version
Mono JIT 编译器版本 6.10.0.104(tarball,2020 年 6 月 26 日星期五 19:38:24 UTC) 版权所有 (C) 2002-2014 Novell, Inc、Xamarin Inc 和贡献者。www.mono-project.com TLS: __thread SIGSEGV: altstack Notifications: epoll Architecture: amd64 Disabled: none Misc: softdebug Interpreter: yes LLVM: yes(610) Suspend: hybrid GC: sgen (concurrent by default)
有趣的问题!请让我知道它是否对您有帮助。
推荐阅读
- spring - 我需要处理并发吗?
- php - 在 laravel 5.8 中进行方法调用时,它不会向我返回数据
- python - Loky 初始化程序(JobLib 后端)
- java - Java泛型二义性方法
- python - 如何在机器学习中对服务数据进行 one-hot 编码?
- r - 如何计算向量与 data.frame 的每一列之间的相关性
- api - 我从 laravel api (flutter) 获取数据时遇到问题
- typescript - RxJs 不理解过滤器只会保留字符串
- python - 根据固定的给定值计算允许的最大项目数
- python - 如何修复 Python 中的“ValueError:未知提取方法'jinja2'”错误?(Jinja2 国际化?)