2011-08-14 14 views
8

私はa programming contestone of the problemsに参加しています。入力データに小数点以下の小数が含まれています:0.75がその一例です。HaskellでRationalへの小数部分の解析方法は?

Doubleに解析するのは簡単ですが(私はそれにはreadを使用できます)、精度の低下は苦痛です。 Doubleの比較には非常に注意が必要です(私はそうではありません)。これは、Haskellのデータ型がRationalなので冗長なようです。

これを使用しようとすると、私はreadRationalという文字列を次の形式で提供する必要があることを発見しました:numerator % denominator、私は明らかに持っていません。

だから、質問は次のとおりです。

Rationalに分数の10進数表現を解析する最も簡単な方法は何ですか?

オンラインジャッジに追加のライブラリをインストールすることはできないため、外部依存関係の数も考慮する必要があります。あなたが欲しい

答えて

15

機能がNumeric.readFloat次のとおりです。

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

ありがとうございました!これは機能します。 – Rotsor

+6

負の数を読み取れるようにするには、 'readSigned'を追加するとよいでしょう。' fst。 $ readSigned readFloat "-3.14" :: Rational' – newacct

3

方法次(のGHCiセッション)について:あなたが適切にあなたのイプシロンを選択する必要があります。もちろん、

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

+0

これは良いアイデアです!私はこれが、ほとんどの状況で 'toRational'の代わりに使われるべきだと思います! – Rotsor

+0

残念ながら、イプシロンの選択はここでは明白ではありません。例えば、 'approxRational 0.999 0.0001'は' 909%910'です。これは私が望むものではありません。この場合に使用する適切なイプシロンは「0.000001」(精度2乗?)です。 – 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

関連する問題