2011-08-14 26 views
8

Tôi đã tham gia vào dữ liệu đầu vào a programming contestone of the problems 'bao gồm một số thập phân theo định dạng thập phân: 0.75 là một ví dụ.Làm cách nào để phân tích một phần thập phân thành Rational trong Haskell?

Phân tích cú pháp thành Double là không đáng kể (Tôi có thể sử dụng read cho điều đó), nhưng mất chính xác là đau đớn. Một trong những cần phải rất cẩn thận với Double so sánh (tôi đã không), mà dường như dư thừa kể từ khi một có Rational kiểu dữ liệu trong Haskell.

Khi cố gắng sử dụng điều đó, tôi đã phát hiện ra rằng để read một Rational người ta phải cung cấp một chuỗi theo định dạng sau: numerator % denominator, mà tôi, rõ ràng là không có.

Vì vậy, câu hỏi là:

cách dễ nhất để phân tích một biểu diễn thập phân của một phần nhỏ vào Rational là gì?

Số lượng phụ thuộc bên ngoài cũng cần được xem xét, vì tôi không thể cài đặt thêm thư viện vào thẩm phán trực tuyến.

Trả lời

15

Chức năng bạn muốn là Numeric.readFloat:

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

Cảm ơn bạn! Những công việc này. – Rotsor

+6

bạn có thể muốn thêm 'readSigned' nếu bạn muốn đọc được số âm:' fst. head $ readSigned readFloat "-3.14" :: Rational' – newacct

3

Làm thế nào về sau (GHCi phiên):

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

Tất nhiên bạn phải chọn epsilon của bạn một cách thích hợp.

+0

Đây là một ý tưởng hay! Tôi nghĩ rằng điều này nên được sử dụng thay vì 'toRational' trong hầu hết các trường hợp! – Rotsor

+0

Thật không may, sự lựa chọn của epsilon là không rõ ràng ở đây. Ví dụ: 'approxRational 0,999 0,0001' là' 909% 910', không phải là điều tôi muốn. Các epsilon thích hợp để sử dụng trong trường hợp này là '0.000001' (chính xác bình phương?) – Rotsor

1

Có lẽ bạn muốn nhận được thêm điểm trong cuộc thi để thực hiện điều đó cho mình:

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

Tôi không nghĩ như vậy. Trong các cuộc thi như vậy chỉ có thời gian nộp và các vấn đề chính xác. Giải pháp tốt đẹp vẫn còn, đủ ngắn để mã trong trường hợp khẩn cấp. – Rotsor

Các vấn đề liên quan