不,这不是另一个"Why is (1/3.0)*3 != 1"个问题.

我最近读了很多关于浮点的书;具体地说,same calculation might give different results是如何在不同的架构或优化设置上运行的.

这是存储重播的视频游戏的一个问题,或者是peer-to-peer networked(与服务器客户端相反),它们依赖于所有客户端在每次运行程序时生成完全相同的结果——一个浮点计算中的微小差异可能会导致不同机器(甚至on the same machine!)上的游戏状态截然不同

即使在"跟随"IEEE-754的处理器中也会发生这种情况,主要是因为某些处理器(即x86)使用double extended precision.也就是说,它们使用80位寄存器来执行所有计算,然后截断为64位或32位,从而导致不同于使用64位或32位进行计算的机器的舍入结果.

我已经在网上看到了这个问题的几种解决方案,但都是C++,而不是C语言:

  • 使用_controlfp_s(Windows)、_FPU_SETCW(Linux?)和,或fpsetprec(BSD).
  • 始终以相同的优化设置运行相同的编译器,并要求所有用户具有相同的CPU架构(无跨平台播放).因为我的"编译器"实际上是JIT,它是may optimize differently every time the program is run,我认为这是不可能的.
  • 使用定点运算,同时避免floatdouble.decimal可以用于此目的,但是速度会慢得多,并且System.Math个库函数中没有一个支持它.

那么,如果我只打算支持Windows(而不是Mono)呢?

如果是,is there any way to force my program to run at normal double-precision?

如果不是,are there any libraries that would help保持浮点计算的一致性?

推荐答案

我不知道有什么方法可以让普通的浮点值具有确定性.网抖动允许创建在不同平台上(或在不同版本的.net之间)表现不同的代码.因此,在确定的时间里使用正常的float秒.net代码是不可能的.

我考虑的解决方法是:

  1. 在C#中实现FixedPoint32.虽然这并不难(我已经完成了一半的实现),但值的范围非常小,使用起来很烦人.你必须时刻小心,这样你既不会溢出,也不会失go 太多的精确度.最后,我发现这并不比直接使用整数容易.
  2. 在C#中实现FixedPoint64.我觉得这很难做到.对于某些操作,128位的中间整数会很有用.但是net不提供这种类型.
  3. 实现一个定制的32位浮点.在实现这一点时,缺少BitScanReverse内在特性会引起一些麻烦.但目前我认为这是最有希望的途径.
  4. 使用本机代码进行数学运算.在每次数学运算中都会产生委托调用的开销.

我刚刚开始一个32位浮点数学的软件实现.在我的2.66GHz i3上,它每秒可以进行约7000万次加法/乘法运算.

.net相关问答推荐

为什么Linq中的运算符逻辑不匹配结果,当值为0或在VB. NET中没有

NET 6:控制器方法不可访问

即时窗口中的动态导致Microsoft.CSharp.RuntimeBinder.Binder未定义或导入错误

StreamWriter.Flush() 和 StreamWriter.Close() 有什么区别?

无法加载文件或程序集 Microsoft.Extensions.DependencyInjection.Abstractions,版本 = 1.1.0.0

在 .NET 中获取执行 exe 路径的最佳方法是什么?

单击关闭按钮时隐藏表单而不是关闭

我可以使用 UriTemplate 将非字符串传递给 WCF RESTful 服务吗?

使用 C# 清除文本文件的内容

在 Moq Callback() 调用中设置变量值

如何使用转储文件来诊断内存泄漏?

如何判断对象是否是某种类型的数组?

什么是 Hashtable 的通用版本?

为什么 C# 不推断我的泛型类型?

使用 C# 设置全局热键

C# (.NET) 设计缺陷

Microsoft.Bcl.Build NuGet 包有什么作用?

ConfigurationManager.AppSettings - 如何修改和保存?

Windows 服务在哪个目录中运行?

App.config:用户与应用程序范围