проблема с двойным и рациональным числом - PullRequest
3 голосов
/ 01 апреля 2010

Я пишу функцию, в которой мне нужно прочитать строку, содержащую число с плавающей запятой, и вернуть ее обратно в Rational. Но когда я делаю toRational (read input :: Double), он не превратится, например: 0.9 в 9 % 10, как ожидалось, а вместо этого 81 .....% 9007 ... Thx

Ответы [ 2 ]

10 голосов
/ 01 апреля 2010

Это правильное поведение. Число 0.9 не представляется как Double, не в Haskell, C или Java. Это потому, что Double и Float используют основание 2: они могут точно представлять только определенное подмножество двоичных дробей.

Чтобы получить желаемое поведение, импортируйте модуль Numeric и используйте функцию readFloat. Интерфейс довольно шаткий (используется тип ReadS), поэтому вам придется немного обернуть его. Вот как это можно использовать:

import Numeric
myReadFloat :: String -> Rational -- type signature is necessary here
myReadFloat str =
    case readFloat str of
      ((n, []):_) -> n
      _ -> error "Invalid number"

И, результат:

> myReadFloat "0.9"
9 % 10
2 голосов
/ 01 апреля 2010

Двоичные числа с плавающей запятой не могут точно представлять все числа, которые может использовать base-10. Число, которое вы видите как 0,9, это не точно 0,9, а нечто очень близкое к нему. Никогда не используйте типы с плавающей точкой, где требуется десятичная точность - они просто не могут этого сделать.

...