2 / 2 / 0
Регистрация: 14.09.2014
Сообщений: 82
|
|
1
|
Новые типы. Помогите доделать задачку
17.10.2014, 20:44. Показов 399. Ответов 0
нужно Для операций назначить тип экземпляром класса Integral и RealFrac
Haskell | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
| import Numeric
data R a = a :/: a deriving (Read, Show)
--------------------------------------------------------------------------
-- числитель
numer :: (Integral a) => R a -> a
numer (a :/: _) = a
-- знаменатель
denom :: (Integral a) => R a -> a
denom (_ :/: b) = b
rReverse :: (Integral a) => R a -> R a
rReverse (n :/: d) = (d :/: n)
-- упрощение дроби
reduce :: (Integral a) => R a -> R a
reduce a = (n ` div ` common) :/: (d ` div ` common)
where (n :/: d) = a
common = (gcd n d) * (signum d)
-- сложение дробей
rAdd :: (Integral a) => R a -> R a -> R a
a ` rAdd ` b = reduce $ (an * bd + bn * ad) :/: (ad * bd)
where (an :/: ad) = a
(bn :/: bd) = b
-- вычитание дробей
rSub :: (Integral a) => R a -> R a -> R a
a ` rSub ` b = a ` rAdd ` ((- bn) :/: bd)
where bn = numer b
bd = denom b
-- умножение
rMul :: (Integral a) => R a -> R a -> R a
a ` rMul ` b = reduce $ (an * bn) :/: (ad * bd)
where (an :/: ad) = a
(bn :/: bd) = b
-- деление
rDiv :: (Integral a) => R a -> R a -> R a
a ` rDiv ` b = a ` rMul ` (bd :/: bn)
where bn = numer b
bd = denom b
-- модуль
rAbs :: (Integral a) => R a -> R a
rAbs (n :/: d) = reduce $ (abs n) :/: (abs d)
-- знаковое значение
rSignum :: (Num a1, Num a, Ord a1) => R a1 -> R a
rSignum (n :/: d)
| n == 0 = (0 :/: 1)
| (n > 0) == (d > 0) = (1 :/: 1)
| otherwise = ((- 1) :/: 1)
-- функция проверки на равенство для реализации instance класса Eq
rEq :: (Integral a) => R a -> R a -> Bool
a ` rEq ` b = (a ` rCompare ` b) == EQ
-- функция сравнения для реализации instance класса Ord
rCompare :: (Num a, Ord a) => R a -> R a -> Ordering
a ` rCompare ` b
| (signum ad) == (signum bd) = (an * bd) ` compare ` (bn * ad)
| otherwise = (bn * ad) ` compare ` (an * bd)
where (an :/: ad) = a
(bn :/: bd) = b
-- instance класса Num
instance (Integral a) => Num (R a) where
(+) a b = a ` rAdd ` b
(-) a b = a ` rSub ` b
(*) a b = a ` rMul ` b
abs a = rAbs a
signum a = rSignum a
fromInteger a = (fromInteger (a) :/: 1)
-- instance класса Eq
instance (Integral a) => Eq (R a) where
(==) a b = a ` rEq ` b
-- instance класса Ord
instance (Integral a) => Ord (R a) where
compare = rCompare
toRat :: RealFloat a => a -> R Integer
toRat x = reduce (( truncate $ x * 100500) :/: 100500)
-- функция извлечения приближенного вещественного
-- значения с заданной точностью в виде дроби
myApproxRational :: RealFloat a => a -> a -> R Integer
myApproxRational x eps = simplest (x - eps) (x + eps)
where
simplest x y
| y < x = simplest y x
| x > 0 = simplest' n d n' d'
| x == y = xr
| y < 0 = - simplest' (- n') d' (- n) d
| otherwise = (0 :/: 1)
where
xr @ (n :/: d) = reduce $ toRat x
(n' :/: d') = reduce $ toRat y
simplest' n d n' d'
| r == 0 = (q :/: 1)
| q /= q = (q + 1) :/: 1
| otherwise = (q * n'' + d'') :/: n''
where
(q, r) = quotRem n d
(q', r') = quotRem n' d'
(n'' :/: d'') = simplest' d' r' d r
--------------------------------------------------------------------------
-- примеры
main = do
let i1 = - 1 :/: 2
let i2 = 1 :/: 4
let i3 = 2 :/: 8
let i4 = (- 1 :/: 8) + ( 1 :/: 4)
print $ "tests"
-- вывод значений
print $ i1
print $ i2
print $ i3
print $ i4
-- арифметические операции
print $ i3 + i2
print $ i3 - i2
print $ i3 * i2
print $ i3 ` rDiv ` i2
print $ abs i1
print $ signum i1
-- операции сравнения векторов (сравнение модулей векторов)
print $ i1 < i4
print $ i1 > i4
print $ i2 == i3
print $ i1 /= i1
print $ i1 == i1
-- функция приближеня дробей
print $ myApproxRational (2 / 6) 0.1
print $ myApproxRational 3.14 0.01
print $ myApproxRational 3.14 0.001 |
|
0
|