fork download
  1. # @file bignum.002.py
  2. # @ingroup experimental
  3. # Experimental big-number representation.
  4. # (sign magnitude version)
  5. # @date 11/22/2024
  6.  
  7. import itertools
  8. import operator
  9. import random
  10.  
  11. class Num:
  12. base = 2**8
  13.  
  14. def __init__(self, init):
  15. if isinstance(init, tuple):
  16. self.m = init[0]
  17. self.s = init[1]
  18. else:
  19. self.m = iton(abs(init), Num.base)
  20. self.s = init < 0
  21.  
  22. def __neg__(self):
  23. return Num(nneg(self.m, self.s))
  24.  
  25. def __add__(self, other):
  26. return Num(nadd(self.m, self.s, other.m, other.s, Num.base))
  27.  
  28. def __sub__(self, other):
  29. return Num(nsub(self.m, self.s, other.m, other.s, Num.base))
  30.  
  31. def __mul__(self, other):
  32. return Num(nmul(self.m, self.s, other.m, other.s, Num.base))
  33.  
  34. def __floordiv__(self, other):
  35. return Num(ndiv(self.m, self.s, other.m, other.s, Num.base)[0])
  36.  
  37. def __mod__(self, other):
  38. return Num(ndiv(self.m, self.s, other.m, other.s, Num.base)[1])
  39.  
  40. def __str__(self):
  41. return '-' * self.s + ntos(self.m, Num.base)
  42.  
  43. def __repr__(self):
  44. return str((self.m, self.s))
  45.  
  46. # Utility.
  47.  
  48. def _iszero(a):
  49. return len(a) == 1 and a[0] == 0
  50.  
  51. def _fixsign(a, s):
  52. return a, s and not _iszero(a)
  53.  
  54. def _zeroextend(a, n):
  55. return a[:] + [0] * (n - len(a))
  56.  
  57. def _zeroreduce(a):
  58. n = len(a)
  59. while n != 1 and a[n-1] == 0:
  60. n -= 1
  61. return a[:n]
  62.  
  63. def _inplace_mul1(r, x, c, base):
  64. for i in range(len(r)):
  65. c, r[i] = divmod(r[i] * x + c, base)
  66. return c, r
  67.  
  68. # Convert.
  69.  
  70. def iton(x, base):
  71. r = []
  72. while True:
  73. x, y = divmod(x, base)
  74. r.append(y)
  75. if x == 0:
  76. return r
  77.  
  78. def nton(a, base1, base2):
  79. r = [0]
  80. for x in reversed(a):
  81. c = _inplace_mul1(r, base1, x, base2)[0]
  82. if c != 0:
  83. r.extend(iton(c, base2))
  84. return r
  85.  
  86. def ntos(a, base):
  87. return ''.join(map(str, reversed(nton(a, base, 10))))
  88.  
  89. # Compare.
  90.  
  91. def _cmp(x, y):
  92. return -1 if x < y else 1
  93.  
  94. def ncmp(a, b):
  95. n = len(a)
  96. m = len(b)
  97. if n != m:
  98. return _cmp(n, m)
  99. for x, y in zip(reversed(a), reversed(b)):
  100. if x != y:
  101. return _cmp(x, y)
  102. return 0
  103.  
  104. # Shift.
  105.  
  106. def nshl(a, n):
  107. return _zeroreduce([0] * n + a[:])
  108.  
  109. def nshr(a, n):
  110. return _zeroextend(a[n:], 1)
  111.  
  112. # Negate.
  113.  
  114. def nneg(a, s):
  115. return _fixsign(a.copy(), not s)
  116.  
  117. # Add.
  118.  
  119. def _add(a, b, base, op):
  120. n = 1 + max(len(a), len(b))
  121. r = _zeroextend(a, n)
  122. b = _zeroextend(b, n)
  123. c = 0
  124. for i in range(n):
  125. c, r[i] = divmod(op(r[i], b[i] + abs(c)), base)
  126. return _zeroreduce(r)
  127.  
  128. def nadd(a, s, b, t, base):
  129. if s == t:
  130. op = operator.add
  131. else:
  132. op = operator.sub
  133. if ncmp(a, b) < 0:
  134. a, b, s = b, a, t
  135. return _fixsign(_add(a, b, base, op), s)
  136.  
  137. # Subtract.
  138.  
  139. def nsub(a, s, b, t, base):
  140. return nadd(a, s, b, _fixsign(b, not t)[1], base)
  141.  
  142. # Multiply.
  143.  
  144. def _mul1(a, x, base):
  145. n = 1 + len(a)
  146. return _zeroreduce(_inplace_mul1(_zeroextend(a, n), x, 0, base)[1])
  147.  
  148. def _mul(a, b, base):
  149. if _iszero(b):
  150. return [0]
  151. return _add(_mul1(a, b[0], base), _mul(nshl(a, 1), nshr(b, 1), base),
  152. base, operator.add)
  153.  
  154. def nmul(a, s, b, t, base):
  155. return _fixsign(_mul(a, b, base), s != t)
  156.  
  157. # Divide.
  158.  
  159. def _div2(a, b):
  160. if len(a) < len(b):
  161. q, r = [0], a
  162. else:
  163. q, r = _div2(a, nshl(b, 1))
  164. q = nshl(q, 1)
  165. if ncmp(r, b) >= 0:
  166. q = _add(q, [1], 2, operator.add)
  167. r = _add(r, b, 2, operator.sub)
  168. return q, r
  169.  
  170. def _div(a, b, base):
  171. a = nton(a, base, 2)
  172. b = nton(b, base, 2)
  173. q, r = _div2(a, b)
  174. q = nton(q, 2, base)
  175. r = nton(r, 2, base)
  176. return q, r
  177.  
  178. def ndiv(a, s, b, t, base):
  179. if _iszero(b):
  180. raise ZeroDivisionError
  181. q, r = _div(a, b, base)
  182. if s != t and not _iszero(r):
  183. q = _add(q, [1], base, operator.add)
  184. r = _add(b, r, base, operator.sub)
  185. return _fixsign(q, s != t), _fixsign(r, t)
  186.  
  187. # Test.
  188.  
  189. def _test(n, z, op, nozeroy=False):
  190. for x, y in itertools.product(z, repeat=2):
  191. if not nozeroy or y != 0:
  192. u = int(str(op(Num(x), Num(y))))
  193. v = op(x, y)
  194. assert u == v, f'{op}({x}, {y})\nExpected:{v}, Got:{u}'
  195. z = Num.base ** 3
  196. for _ in range(n):
  197. x = random.randint(-z, z)
  198. y = random.randint(-z, z)
  199. if not nozeroy or y != 0:
  200. u = int(str(op(Num(x), Num(y))))
  201. v = op(x, y)
  202. assert u == v, f'{op}({x}, {y})\nExpected:{v}, Got:{u}'
  203.  
  204. n = 1000
  205. w = Num.base
  206. z = (0, 1, -1, w, -w, w-1, 1-w)
  207. _test(n, z, operator.add)
  208. _test(n, z, operator.sub)
  209. _test(n, z, operator.mul)
  210. _test(n, z, operator.floordiv, True)
  211. _test(n, z, operator.mod, True)
  212.  
  213. def show1(a):
  214. print(repr(a), a, sep='; ')
  215.  
  216. def _show(z, op, nozeroy=False):
  217. print(op)
  218. for x, y in itertools.product(z, repeat=2):
  219. if not nozeroy or y != 0:
  220. show1(op(Num(x), Num(y)))
  221.  
  222. w = Num.base
  223. z = (0, 1, -1, w, -w)
  224. _show(z, operator.add)
  225. _show(z, operator.sub)
  226. _show(z, operator.mul)
  227. _show(z, operator.floordiv, True)
  228. _show(z, operator.mod, True)
  229.  
  230. def factorial(n):
  231. r = Num(1)
  232. for i in range(2, n+1):
  233. r *= Num(i)
  234. return r
  235.  
  236. print(factorial)
  237. for i in range(5):
  238. show1(factorial(10*i))
Success #stdin #stdout 0.28s 10324KB
stdin
Standard input is empty
stdout
<built-in function add>
([0], False); 0
([1], False); 1
([1], True); -1
([0, 1], False); 256
([0, 1], True); -256
([1], False); 1
([2], False); 2
([0], False); 0
([1, 1], False); 257
([255], True); -255
([1], True); -1
([0], False); 0
([2], True); -2
([255], False); 255
([1, 1], True); -257
([0, 1], False); 256
([1, 1], False); 257
([255], False); 255
([0, 2], False); 512
([0], False); 0
([0, 1], True); -256
([255], True); -255
([1, 1], True); -257
([0], False); 0
([0, 2], True); -512
<built-in function sub>
([0], False); 0
([1], True); -1
([1], False); 1
([0, 1], True); -256
([0, 1], False); 256
([1], False); 1
([0], False); 0
([2], False); 2
([255], True); -255
([1, 1], False); 257
([1], True); -1
([2], True); -2
([0], False); 0
([1, 1], True); -257
([255], False); 255
([0, 1], False); 256
([255], False); 255
([1, 1], False); 257
([0], False); 0
([0, 2], False); 512
([0, 1], True); -256
([1, 1], True); -257
([255], True); -255
([0, 2], True); -512
([0], False); 0
<built-in function mul>
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([1], False); 1
([1], True); -1
([0, 1], False); 256
([0, 1], True); -256
([0], False); 0
([1], True); -1
([1], False); 1
([0, 1], True); -256
([0, 1], False); 256
([0], False); 0
([0, 1], False); 256
([0, 1], True); -256
([0, 0, 1], False); 65536
([0, 0, 1], True); -65536
([0], False); 0
([0, 1], True); -256
([0, 1], False); 256
([0, 0, 1], True); -65536
([0, 0, 1], False); 65536
<built-in function floordiv>
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([1], False); 1
([1], True); -1
([0], False); 0
([1], True); -1
([1], True); -1
([1], False); 1
([1], True); -1
([0], False); 0
([0, 1], False); 256
([0, 1], True); -256
([1], False); 1
([1], True); -1
([0, 1], True); -256
([0, 1], False); 256
([1], True); -1
([1], False); 1
<built-in function mod>
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([1], False); 1
([255], True); -255
([0], False); 0
([0], False); 0
([255], False); 255
([1], True); -1
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
<function factorial at 0x14dcab135b80>
([1], False); 1
([0, 95, 55], False); 3628800
([0, 0, 180, 130, 124, 103, 195, 33], False); 2432902008176640000
([0, 0, 0, 84, 221, 245, 93, 134, 150, 15, 55, 246, 19, 13], False); 265252859812191058636308480000000
([0, 0, 0, 0, 64, 37, 5, 255, 100, 222, 15, 8, 126, 242, 199, 132, 27, 232, 234, 142], False); 815915283247897734345611269596115894272000000000