#haskell
#haskell
Вопрос:
Я хочу взять что-то вроде 1/7 (0,142857142857 …) и преобразовать его в «0.142857142857» или «142857142857» [1,4,2,8,5,7,1,4,2,8,5,7]. Используя
map (( ) (-48) . ord) . show
работает, когда знаменатель маленький, но с большими знаменателями Haskell начинает использовать научную нотацию. Как я могу последовательно преобразовать дробное число в список его цифр?
Комментарии:
1. Кстати, проверьте
Data.Char.digitToInt
.2. Другим способом
( ) (-48)
можно записатьsubtract 48
.
Ответ №1:
Это не полное решение, но оно поможет вам начать. Это возвращает список цифр для числа от нуля до единицы. Оберните его соответствующим методом, чтобы получить вывод в нужном вам формате.
digits :: (RealFrac a) => a -> [Int]
digits 0 = []
digits x = d : digits (10*x - fromIntegral d)
where
d = floor (10*x)
Играем с этим:
ghci> digits (1/4)
[2,5]
ghci> digits (1/3)
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,7,2,7,3,8,6,0,0,9,
9,9,5,8,2,5,5,8,8,7,0,3,1,5,5,5,1,7,5,7,8,1,2,5]
-- rounding error got us, let's use an exact rational
ghci> import Data.Ratio
ghci> digits (1%3)
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
...
Естественно, вы можете взять из бесконечного списка цифр, чтобы получить префикс.
Комментарии:
1. Эта функция немного забавна, если вы передаете ей цифры больше 1 .
digits (4%3) = [13, 3, 3, 3, ...]
. =)
Ответ №2:
Например, это покажет от 1/7 до 12 знаков после запятой. Он никогда не будет использовать научную нотацию.
Numeric.showFFloat (Just 12) (1/7) ""
Комментарии:
1. Что это
Numeric
за модуль?
Ответ №3:
Я полагаю, это простой способ.
showDigits :: Int -> Double -> String
showDigits n x = show (floor x) "." showRest n x
showRest :: Int -> Double -> String
showRest n x | n <= 0 = ""
| otherwise = digitToInt dig : showRest (pred n) x'
where dig = (floor x') `mod` 10
x' = x * 10
Однако это может быть настолько точным, насколько Double
соответствует представление. Кроме того, он никогда не округляет последнюю цифру в большую сторону; он просто показывает ее (округляет в меньшую сторону). Тестирование:
ghci> showDigits 5 (1/7)
"0.14285"
Ответ №4:
Я думаю, вам нужен Text.Printf.printf:
import Data.Char
import Text.Printf
getDigits :: Double -> [Int]
getDigits=map ((subtract 48).Data.Char.ord) . (Text.Printf.printf "%f")