Advertisement
Guest User

Untitled

a guest
Oct 28th, 2016
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.78 KB | None | 0 0
  1. open Printf
  2.  
  3. module Bigint = struct
  4.  
  5. type sign = Pos | Neg
  6. type bigint = Bigint of sign * int list
  7. let radix = 1000
  8. let radixlen = 3
  9.  
  10. let car = List.hd
  11. let cdr = List.tl
  12. let map = List.map
  13. let reverse = List.rev
  14. let strcat = String.concat
  15. let strlen = String.length
  16. let strsub = String.sub
  17. let zero = Bigint (Pos, [])
  18.  
  19. let charlist_of_string str =
  20. let last = strlen str - 1
  21. in let rec charlist pos result =
  22. if pos < 0
  23. then result
  24. else charlist (pos - 1) (str.[pos] :: result)
  25. in charlist last []
  26.  
  27. let bigint_of_string str =
  28. let rec makelist str first len =
  29. if first = len
  30. then []
  31. else let diff = len - first in
  32. let len' = len - radixlen in
  33. if diff < radixlen
  34. then [int_of_string (strsub str first diff)]
  35. else (int_of_string (strsub str len' radixlen))
  36. :: (makelist str first len')
  37. in let len = strlen str
  38. in if len = 0
  39. then Bigint (Pos, [])
  40. else if str.[0] = '_'
  41. then Bigint (Neg, makelist str 1 len)
  42. else Bigint (Pos, makelist str 0 len)
  43.  
  44. let string_of_bigint (Bigint (sign, value)) =
  45. match value with
  46. | [] -> "0"
  47. | value -> let reversed = reverse value
  48. in strcat ""
  49. ((if sign = Pos then "" else "-") ::
  50. (string_of_int (car reversed)) ::
  51. (map (sprintf "%03d") (cdr reversed)))
  52.  
  53. let rem (Bigint (neg1, value1)) (Bigint (neg2, value2)) =
  54. if (car value2) <> 0 then (
  55. if neg1 = neg2
  56. then Bigint(neg1, snd(div' value1 value2 [0]))
  57. else Bigint(Neg, snd(div' value1 value2 [0]))
  58. )
  59. else (printf "dc: remainder by zero\n"; Bigint(Pos,[0]))
  60.  
  61. let rec cmp list1 list2 = match (list1, list2) with
  62. | list1, [] -> 1
  63. | [], list2 -> 0
  64. | car1::cdr1, car2::cdr2 ->
  65. if car1 > car2
  66. then 1
  67. else if car2 > car1
  68. then 0
  69. else cmp cdr1 cdr2
  70.  
  71. let rec sub' list1 list2 carry = match (list1, list2, carry) with
  72. | list1, [], 0 -> list1
  73. | [], list2, 0 -> list2
  74. | list1, [], carry -> sub' list1 [carry] 0
  75. | [], list2, carry -> sub' [carry] list2 0
  76. | car1::cdr1, car2::cdr2, carry ->
  77. let diff = car1 - car2 - carry
  78. in diff mod radix :: sub' cdr1 cdr2 (diff / radix)
  79.  
  80. let sub (Bigint (neg1, value1)) (Bigint (neg2, value2)) =
  81. if (neg1 = Pos && neg2 = Pos)
  82. then (
  83. if (cmp value1 value2) = 1
  84. then Bigint (neg1, sub' value1 value2 0)
  85. else Bigint (Neg, sub' value2 value1 0))
  86. else if (neg1 = Neg && neg2 = Neg)
  87. then (
  88. if (cmp value1 value2) = 1
  89. then Bigint(neg1, add' value1 value2 0)
  90. else Bigint(Pos, sub' value2 value1 0))
  91. else Bigint(neg1, add' value1 value2 0)
  92.  
  93. let rec add' list1 list2 carry = match (list1, list2, carry) with
  94. | list1, [], 0 -> list1
  95. | [], list2, 0 -> list2
  96. | list1, [], carry -> add' list1 [carry] 0
  97. | [], list2, carry -> add' [carry] list2 0
  98. | car1::cdr1, car2::cdr2, carry ->
  99. let sum = car1 + car2 + carry
  100. in sum mod radix :: add' cdr1 cdr2 (sum / radix)
  101.  
  102. let add (Bigint (neg1, value1)) (Bigint (neg2, value2)) =
  103. if neg1 = neg2
  104. then Bigint (neg1, add' value1 value2 0)
  105. else if (neg1 = Pos && neg2 = Neg)
  106. then (
  107. if (cmp value1 value2) = 1
  108. then Bigint(neg1, sub' value1 value2 0)
  109. else Bigint(neg2, sub' value2 value1 0))
  110. else if (neg1 = Neg && neg2 = Pos)
  111. then (
  112. if (cmp value1 value2) = 1
  113. then Bigint(neg1, sub' value1 value2 0)
  114. else Bigint(neg2, sub' value2 value1 0))
  115. else (
  116. if (cmp value1 value2) = 1
  117. then Bigint(neg1, sub' value1 value2 0)
  118. else Bigint(neg2, sub' value2 value1 0)
  119. )
  120.  
  121. let rec div' value1 value2 ans =
  122. if (cmp value1 value2) = 0
  123. then (ans, value1)
  124. else (div' (sub' value1 value2 0) value2 (add' ans [1] 0))
  125.  
  126. let div (Bigint (neg1, value1)) (Bigint (neg2, value2)) =
  127. if (car value2) <> 0 then (
  128. if neg1 = neg2
  129. then Bigint(Pos, fst(div' value1 value2 [0]))
  130. else Bigint(Neg, fst(div' value1 value2 [0]))
  131. )
  132. else(printf "dc: division by zero\n"; Bigint(Pos,[0]))
  133.  
  134. let rec mul' val1 val2 =
  135. if (car val2) = 1
  136. then val1
  137. else (add' val1 (mul' val1 (sub' val2 [1] 0)) 0)
  138.  
  139. let mul (Bigint (neg1, value1)) (Bigint (neg2, value2)) =
  140. if neg1 = neg2
  141. then Bigint (Pos, mul' value1 value2)
  142. else Bigint (Neg, mul' value1 value2)
  143.  
  144. let rec pow' val1 val2 =
  145. if (car val2) = 1
  146. then val1
  147. else (mul' val1 (pow' val1 (sub' val2 [1] 0)))
  148.  
  149. let pow (Bigint (neg1, value1)) (Bigint (neg2, value2)) =
  150. if neg2 = Neg
  151. then (Bigint (Pos, [])) (*May need be 0 *)
  152. else if neg1 = Pos
  153. then (Bigint (neg1, pow' value1 value2))
  154. else if rem (Bigint (Pos, value2)) (Bigint (Pos, [2])) =
  155. (Bigint (Pos, [1]))
  156. then (Bigint (Neg, pow' value1 value2))
  157. else (Bigint (Pos, pow' value1 value2))
  158.  
  159.  
  160. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement