2011-08-14 61 views
8

我一直參與a programming contestone of the problems'輸入數據包含一個十進制格式的小數:0.75就是一個例子。如何在Haskell中將小數部分解析爲Rational?

解析成Double是微不足道的(我可以使用read),但精度的損失是痛苦的。需要對Double比較(我不是)非常小心,這似乎是多餘的,因爲在Haskell中有一個Rational數據類型。

當試圖使用它時,我發現read a Rational必須提供以下格式的字符串:numerator % denominator,這顯然沒有。

所以,問題是:

什麼是解析分數的十進制表示到Rational最簡單的方法?

也應該考慮外部依賴的數量,因爲我無法在網上裁判中安裝額外的庫。

回答

15

你想要的功能是Numeric.readFloat

Numeric Data.Ratio> fst . head $ readFloat "0.75" :: Rational 
3 % 4 
+0

謝謝!這工作。 – Rotsor

+6

如果您想要讀取負數:'fst,您可能需要添加'readSigned'。 head $ readSigned readFloat「-3.14」:: Rational' – newacct

3

如何以下(GHCI會話):

> :m + Data.Ratio 
> approxRational (read "0.1" :: Double) 0.01 
1 % 10 

當然,你必須適當地選擇你的-5次方。

+0

這是個好主意!我認爲這應該在大多數情況下用來代替'toRational'! – Rotsor

+0

不幸的是,epsilon的選擇在這裏並不明顯。例如,'approxRational 0.999 0.0001'是'909%910',這不是我想要的。在這種情況下使用的正確的epsilon是「0.000001」(精度平方?) – Rotsor

1

也許你會得到加分的較量中爲自己實現它:

import Data.Ratio ((%)) 

readRational :: String -> Rational 
readRational input = read intPart % 1 + read fracPart % (10^length fracPart) 
    where (intPart, fromDot) = span (/='.') input 
     fracPart   = if null fromDot then "0" else tail fromDot 
+0

我不這麼認爲。在這樣的比賽中,只有提交時間和正確性很重要。好的解決方案仍然足夠短,可以在緊急情況下編碼。 – Rotsor

相關問題