-9,007,199,254,740,992和9,007,199,254,740,991之間的所有整數都可以用雙精度表示。(請繼續閱讀)
上限值推導爲2^53 - 1。如果你原諒我的十六進制語法,它的內部表示就像(0x1.fffffffffffff * 2^52)。
在此範圍之外,如果它們是2的冪的倍數,則許多整數仍可以精確地表示。
任何可以精確地表示將因此9,007,199,254,740,991 * (2^1023)
,比Decimal.MaxValue
甚至更高,但是這是一個毫無意義的事實,因爲該值不刻意去改變,例如,當你在減去1
的最大整數算術。
根據評論和進一步的研究,我添加了C#的.NET和Mono實現的相關信息,這些實現將您和我可能想要創建的大多數結論進行相關。
Math.Pow
似乎並不保證任何具體的準確性,它似乎提供一點或比什麼double
可以代表兩個少。這對於浮點函數來說並不太令人意外。英特爾浮點硬件沒有指數運算指令,我期望計算涉及指令,其中間結果會失去一些精度。如果需要整體精度,可以使用BigInteger.Pow
。
但是,即使是(decimal)(double)9007199254740991M
也會導致往返行程違規。然而,這次是known bug,這直接違反了C#規範的第6.2.1節。有趣的是,即使在Mono 2.8中我也看到了同樣的錯誤。 (引用的來源表明,這種轉換錯誤可以多值較低連撞。)
雙擊文字是那麼圓,但還是有一點:9007199254740991D打印出來作爲9007199254740990D。當解析字符串文字時(在上下限根據「小數點後的第一個零」收斂到相同的double
值之前),這是內部乘法的僞像。這又違反了C#規範,這次是第9.4.4.3節。
不像C,C#有沒有十六進制浮點文字,所以我們不能避免10乘以任何其他語法,也許除了通過Decimal
或BigInteger
去,如果這些只提供了準確的轉換操作符。我還沒有測試BigInteger
。
上面幾乎可以讓你想知道C#是否沒有發明自己的精確度較低的浮點格式。不,第11.1.6款提及64位IEC 60559表示。所以上面的確是bug。
所以,最後,你應該能夠在雙重精確,以適應甚至9007199254740991M,但它是相當大的挑戰在地方獲得的價值!
的道德故事的是,傳統的信念,「算術應該只比數據和預期的結果更精確」是錯誤的,因爲this famous article演示(第36頁),儘管在不同的情況下編程語言。
除非必須,否則不要將整數存儲在浮點變量中。
我不確定是否可以有任何最大值,因爲這樣的一些浮點數不能用double精確表示,並且存在精度的損失,不需要在更高的水平,因此 – V4Vendetta