2009-08-11 39 views
0

好吧,我有兩個功能,其中第一個看起來像這樣:f#整數浮點模數1.0 = 1.0?

let dlth x = float (x.ToString().Length) 

這需要一個浮動,並返回的位數,這部分工作正常。第二個功能是這樣的:

let droot x = ((x ** (1./(dlth x))) % 1.) 

它接受一個浮體和它升高至等於1.0 /(數量的數字)的冪,然後取結果和和模數1.0。對於整數應該是零。

因此對於droot36。它需要(36.0 **(1.0/2.0))這是6.0,然後6.0 mod 1.0等於0.0;

現在,這工作正常,直到我嘗試數字81.0。 (以及所有應該工作的數字高於81),由於某種原因返回1.0,拋出我的模式匹配。有人可以告訴我爲什麼會發生這種情況嗎?

PostScript:這是項目歐拉解決方案的一部分。如果您知道哪個問題,請請勿發佈項目歐拉解決方案。我只需要幫助,找出爲什麼模數返回有趣的結果

回答

8

浮點算術充滿了任何語言的危險。在我的盒子

printfn "%f" (0.9999999999999 % 1.0)   

打印

1.000000 

希望這將有助於引導你在正確的方向。如果你真的想知道float是否是一個整數,那麼例如減去最接近的整數並查看絕對值是否小於某個ε(例如0.00001)是一個體面的賭注。

+0

我明白你的意思了,但我認爲用我檢查的數字範圍來創建一個適用於所有事情的測試是不可能的。我想我要做的是看看我是否可以重做它,以避免完全浮動。 – AvatarOfChronos 2009-08-11 15:06:11

0

我同意Brian依賴精確的浮點表示是危險的,但我無法重現您的問題。對我而言,droot 81.0給出了0.0的預期結果。你使用的是什麼版本的F#?你在.NET或Mono上運行?

+0

我試過了。唯一的區別是問題開始的地方。在.net上,它在216上開始變得有趣。在單聲道上,它開始在81上表現得有趣。單聲道和.net都有相同的問題,它們返回一個錯誤的模數。我正在使用F#1.9.6.16 – AvatarOfChronos 2009-08-11 15:27:34

+0

是的,問題是(216.0 **(1.0/3.0))給出5.9999999999999991 ...模數運算符然後給出0.9 ...,顯示爲1.0。通過簡單的平等比較,你可以向自己證明它實際上不是1.0。不幸的是,你需要想出一個更強大的方法來計算你想要的。 – kvb 2009-08-11 16:05:55

+0

我沒有看到216的立方根是如何回到5.9999999 ... 1。 猜測我將不得不深入.Net如何做浮點數學,看看我可以瞭解它。 – AvatarOfChronos 2009-08-11 16:20:53

1

如果您的浮動不準確,您可以使用.NET的decimal數據類型(可以表示以10爲底的所有數字)表示性能。除此之外,使用更高的精度(double)或整數數學。

相關問題