2011-08-14 17 views
8

Uczestniczyłem w a programming contest i one of the problems "danych wejściowych zawartych w liczbie ułamkowej w formacie dziesiętnym: 0.75 jest jednym z przykładów.Jak przeanalizować ułamek dziesiętny w produkcie Rational w języku Haskell?

Parsowanie tego w Double jest trywialne (mogę użyć do tego celu read), ale utrata precyzji jest bolesna. Trzeba być bardzo ostrożnym przy porównywaniu (nie byłem), co wydaje się zbędne, ponieważ ma się typ danych Rational w Haskell.

Podczas próby użycia tego odkryłem, że do read należy podać Rational w następującym formacie: numerator % denominator, którego oczywiście nie mam.

Więc pytanie brzmi:

Jaki jest najprostszy sposób analizowania reprezentację dziesiętną ułamka do Rational?

Liczba zewnętrznych zależności również powinna być wzięta pod uwagę, ponieważ nie mogę zainstalować dodatkowych bibliotek w internetowym sądzie.

Odpowiedz

15

Funkcja chcesz to Numeric.readFloat:

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

Dziękujemy! To działa. – Rotsor

+6

możesz chcieć dodać 'readSigned', jeśli chcesz móc odczytać liczby ujemne:' fst. head $ readSigned readFloat "-3.14" :: Rational' – newacct

3

Jak o następującym (sesja GHCi):

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

Oczywiście trzeba wybrać swój epsilon odpowiednio.

+0

To jest dobry pomysł! Myślę, że powinno to być używane zamiast 'toRational' w większości przypadków! – Rotsor

+0

Niestety, wybór epsilon nie jest tutaj oczywisty. Na przykład 'approxRational 0.999 0.0001' to' 909% 910', co nie jest tym, czego chcę. Właściwym epsilonem do użycia w tym przypadku jest '0.000001' (precyzja do kwadratu?) – Rotsor

1

Może chcesz uzyskać dodatkowe punkty w konkursie na realizację to sam:

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

Nie sądzę. W takich konkursach liczy się tylko czas składania i poprawność. Ładne rozwiązanie, wystarczająco krótkie, by kodować w sytuacji awaryjnej. – Rotsor

Powiązane problemy