Как разобрать десятичную дробь в Rational в Haskell? - PullRequest
9 голосов
/ 14 августа 2011

Я принимал участие в соревновании по программированию и одна из проблем 'входные данные включали дробное число в десятичном формате: 0.75 является одним из примеров.

Анализ этого в Double тривиален (я могу использовать read для этого), но потеря точности болезненна. Нужно быть очень осторожным с Double сравнениями (я не был), что кажется избыточным, так как в Haskell есть тип данных Rational.

Пытаясь использовать это, я обнаружил, что для read a Rational нужно предоставить строку в следующем формате: numerator % denominator, которого у меня, очевидно, нет.

Итак, вопрос:

Какой самый простой способ разбить десятичное представление дроби на Rational?

Также следует учитывать количество внешних зависимостей, поскольку я не могу установить дополнительные библиотеки в онлайн-судье.

Ответы [ 3 ]

17 голосов
/ 14 августа 2011

Функция, которую вы хотите: Numeric.readFloat:

Numeric Data.Ratio> fst . head $ readFloat "0.75" :: Rational
3 % 4
3 голосов
/ 14 августа 2011

Как насчет следующего (сеанс GHCi):

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

Конечно, вы должны правильно выбрать эпсилон.

2 голосов
/ 17 сентября 2012

Возможно, вы получите дополнительные очки в конкурсе за самостоятельную реализацию:

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
...