fork(1) 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(_fixsign(self.m.copy(), not 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. t = _fixsign(other.m, not other.s)[1]
  30. return Num(nadd(self.m, self.s, other.m, t, Num.base))
  31.  
  32. def __mul__(self, other):
  33. return Num(nmul(self.m, self.s, other.m, other.s, Num.base))
  34.  
  35. def __floordiv__(self, other):
  36. return Num(ndiv(self.m, self.s, other.m, other.s, Num.base)[0])
  37.  
  38. def __mod__(self, other):
  39. return Num(ndiv(self.m, self.s, other.m, other.s, Num.base)[1])
  40.  
  41. def __str__(self):
  42. return '-' * self.s + ntos(self.m, Num.base)
  43.  
  44. def __repr__(self):
  45. return str((self.m, self.s))
  46.  
  47. # Utility.
  48.  
  49. def _iszero(a):
  50. return len(a) == 1 and a[0] == 0
  51.  
  52. def _fixsign(a, s):
  53. return a, s and not _iszero(a)
  54.  
  55. def _zeroextend(a, n):
  56. return a[:] + [0] * (n - len(a))
  57.  
  58. def _zeroreduce(a):
  59. n = len(a)
  60. while n != 1 and a[n-1] == 0:
  61. n -= 1
  62. return a[:n]
  63.  
  64. def _inplace_mul1(r, x, c, base):
  65. for i in range(len(r)):
  66. c, r[i] = divmod(r[i] * x + c, base)
  67. return c, r
  68.  
  69. # Convert.
  70.  
  71. def iton(x, base):
  72. r = []
  73. while True:
  74. x, y = divmod(x, base)
  75. r.append(y)
  76. if x == 0:
  77. return r
  78.  
  79. def nton(a, base1, base2):
  80. r = [0]
  81. for x in reversed(a):
  82. c = _inplace_mul1(r, base1, x, base2)[0]
  83. if c != 0:
  84. r.extend(iton(c, base2))
  85. return r
  86.  
  87. def ntos(a, base):
  88. return ''.join(map(str, reversed(nton(a, base, 10))))
  89.  
  90. # Compare.
  91.  
  92. def _cmp(x, y):
  93. return -1 if x < y else 1
  94.  
  95. def ncmp(a, b):
  96. n = len(a)
  97. m = len(b)
  98. if n != m:
  99. return _cmp(n, m)
  100. for x, y in zip(reversed(a), reversed(b)):
  101. if x != y:
  102. return _cmp(x, y)
  103. return 0
  104.  
  105. # Shift.
  106.  
  107. def nshl(a, n):
  108. return _zeroreduce([0] * n + a[:])
  109.  
  110. def nshr(a, n):
  111. return _zeroextend(a[n:], 1)
  112.  
  113. # Add.
  114.  
  115. def _add(a, b, base, op):
  116. n = 1 + max(len(a), len(b))
  117. r = _zeroextend(a, n)
  118. b = _zeroextend(b, n)
  119. c = 0
  120. for i in range(n):
  121. c, r[i] = divmod(op(r[i], b[i] + abs(c)), base)
  122. return _zeroreduce(r)
  123.  
  124. def nadd(a, s, b, t, base):
  125. if s == t:
  126. op = operator.add
  127. else:
  128. op = operator.sub
  129. if ncmp(a, b) < 0:
  130. a, b, s = b, a, t
  131. return _fixsign(_add(a, b, base, op), s)
  132.  
  133. # Multiply.
  134.  
  135. def _mul1(a, x, base):
  136. n = 1 + len(a)
  137. return _zeroreduce(_inplace_mul1(_zeroextend(a, n), x, 0, base)[1])
  138.  
  139. def _mul(a, b, base):
  140. if _iszero(b):
  141. return [0]
  142. return _add(_mul1(a, b[0], base), _mul(nshl(a, 1), nshr(b, 1), base),
  143. base, operator.add)
  144.  
  145. def nmul(a, s, b, t, base):
  146. return _fixsign(_mul(a, b, base), s != t)
  147.  
  148. # Divide.
  149.  
  150. def _div2(a, b):
  151. if len(a) < len(b):
  152. q, r = [0], a
  153. else:
  154. q, r = _div2(a, nshl(b, 1))
  155. q = nshl(q, 1)
  156. if ncmp(r, b) >= 0:
  157. q = _add(q, [1], 2, operator.add)
  158. r = _add(r, b, 2, operator.sub)
  159. return q, r
  160.  
  161. def _div(a, b, base):
  162. a = nton(a, base, 2)
  163. b = nton(b, base, 2)
  164. q, r = _div2(a, b)
  165. q = nton(q, 2, base)
  166. r = nton(r, 2, base)
  167. return q, r
  168.  
  169. def ndiv(a, s, b, t, base):
  170. if _iszero(b):
  171. raise ZeroDivisionError
  172. q, r = _div(a, b, base)
  173. if s != t and not _iszero(r):
  174. q = _add(q, [1], base, operator.add)
  175. r = _add(b, r, base, operator.sub)
  176. return _fixsign(q, s != t), _fixsign(r, t)
  177.  
  178. # Test.
  179.  
  180. def _test(n, z, op, nozeroy=False):
  181. for x, y in itertools.product(z, repeat=2):
  182. if not nozeroy or y != 0:
  183. u = int(str(op(Num(x), Num(y))))
  184. v = op(x, y)
  185. assert u == v, f'{op}({x}, {y})\nExpected:{v}, Got:{u}'
  186. z = Num.base ** 3
  187. for _ in range(n):
  188. x = random.randint(-z, z)
  189. y = random.randint(-z, z)
  190. if not nozeroy or y != 0:
  191. u = int(str(op(Num(x), Num(y))))
  192. v = op(x, y)
  193. assert u == v, f'{op}({x}, {y})\nExpected:{v}, Got:{u}'
  194.  
  195. n = 1000
  196. w = Num.base
  197. z = (0, 1, -1, w, -w, w-1, 1-w)
  198. _test(n, z, operator.add)
  199. _test(n, z, operator.sub)
  200. _test(n, z, operator.mul)
  201. _test(n, z, operator.floordiv, True)
  202. _test(n, z, operator.mod, True)
  203.  
  204. def show1(a):
  205. print(repr(a), a, sep='; ')
  206.  
  207. def _show(z, op, nozeroy=False):
  208. print(op)
  209. for x, y in itertools.product(z, repeat=2):
  210. if not nozeroy or y != 0:
  211. show1(op(Num(x), Num(y)))
  212.  
  213. w = Num.base
  214. z = (0, 1, -1, w, -w)
  215. _show(z, operator.add)
  216. _show(z, operator.sub)
  217. _show(z, operator.mul)
  218. _show(z, operator.floordiv, True)
  219. _show(z, operator.mod, True)
  220.  
  221. def factorial(n):
  222. r = Num(1)
  223. for i in range(2, n+1):
  224. r *= Num(i)
  225. return r
  226.  
  227. print(factorial)
  228. for i in range(5):
  229. show1(factorial(10*i))
Success #stdin #stdout 0.27s 10300KB
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 0x14d31f6d09d0>
([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