Dot-Net

確定性浮點和 .NET

  • April 8, 2020

如何保證 .NET 應用程序(例如 C#)中的浮點計算總是產生相同的位精確結果?尤其是在使用不同版本的 .NET 並在不同平台上執行時(x86 與 x86_64)。浮點運算的不准確性無關緊要。

在 Java 中,我會使用 strictfp。在 C/C++ 和其他低級語言中,這個問題基本上是通過訪問 FPU / SSE 控制寄存器來解決的,但這在 .NET 中可能是不可能的。

即使控制了 FPU 控制寄存器,.NET 的 JIT 也會在不同的平台上生成不同的程式碼。在這種情況下,像 HotSpot 這樣的東西會更糟……

為什麼我需要它?我正在考慮編寫一個實時策略 (RTS) 遊戲,它在很大程度上依賴於快速浮點數學以及鎖步模擬。本質上,我只會通過網路傳輸使用者輸入。這也適用於通過儲存使用者輸入來實現回放的其他遊戲。

不是一個選項是:

  • 小數(太慢)
  • 定點值(使用 sqrt、sin、cos、tan、atan 時太慢且太麻煩……)
  • 像 FPS 一樣通過網路更新狀態:發送數百或數千個單位的位置資訊不是一種選擇

有任何想法嗎?

我不確定您的問題的確切答案,但您可以使用 C++ 並在 c++ dll 中完成所有浮動工作,然後通過互選將結果返回給 .Net。

不同平台的 Bitexact 結果令人痛苦。如果您只使用 x86,那應該沒關係,因為 FPU 不會從 32 位更改為 64 位。但問題是超越函式在新處理器上可能更準確。

四個基本操作不應該給出不同的結果,但是您的 VM 可能會優化表達式並且可能會給出不同的結果。因此,正如 Ants 建議的那樣,將您的 add/mul/div/sub 常式編寫為非託管程式碼以確保安全。

對於超越函式,恐怕您必須使用查找表來保證位的準確性。計算例如 4096 個值的結果,將它們儲存為常量,如果需要它們之間的值,則進行插值。這不會給你很大的準確性,但它會很精確。

引用自:https://stackoverflow.com/questions/2376679