blueloveTH 2 năm trước cách đây
mục cha
commit
94bdfaa949
2 tập tin đã thay đổi với 38 bổ sung5 xóa
  1. 29 4
      python/_long.py
  2. 9 1
      tests/09_long.py

+ 29 - 4
python/_long.py

@@ -59,6 +59,17 @@ def ulong_add(a: list, b: list) -> list:
         res.append(carry)
     return res
 
+def ulong_inc_(a: list):
+    a[0] += 1
+    for i in range(len(a)):
+        if a[i] < PyLong_BASE: break
+        a[i] -= PyLong_BASE
+        if i+1 == len(a):
+            a.append(1)
+        else:
+            a[i+1] += 1
+    
+
 def ulong_sub(a: list, b: list) -> list:
     # a >= b
     res = []
@@ -95,6 +106,13 @@ def ulong_divmodi(a: list, b: int):
     ulong_unpad_(res)
     return res, carry
 
+def ulong_divmod(a: list, b: list):
+    q = [0]
+    while ulong_cmp(a, b) >= 0:
+        ulong_inc_(q)
+        a = ulong_sub(a, b)
+    return q, a
+
 def ulong_floordivi(a: list, b: int):
     # b > 0
     return ulong_divmodi(a, b)[0]
@@ -178,6 +196,9 @@ class long:
             self.digits, self.sign = x.digits.copy(), x.sign
         else:
             raise TypeError('expected int or str')
+        
+    def __len__(self):
+        return len(self.digits)
 
     def __add__(self, other):
         if type(other) is int:
@@ -239,16 +260,20 @@ class long:
     #######################################################
     def __divmod__(self, other):
         if type(other) is int:
-            assert type(other) is int and other > 0
-            assert self.sign == 1
+            assert self.sign == 1 and other > 0
             q, r = ulong_divmodi(self.digits, other)
             return long((q, 1)), r
+        if type(other) is long:
+            assert self.sign == 1 and other.sign == 1
+            q, r = ulong_divmod(self.digits, other.digits)
+            assert len(other)>1 or other.digits[0]>0
+            return long((q, 1)), long((r, 1))
         raise NotImplementedError
 
-    def __floordiv__(self, other: int):
+    def __floordiv__(self, other):
         return self.__divmod__(other)[0]
 
-    def __mod__(self, other: int):
+    def __mod__(self, other):
         return self.__divmod__(other)[1]
 
     def __pow__(self, other: int):

+ 9 - 1
tests/09_long.py

@@ -23,4 +23,12 @@ for i in range(29):
 for i in range(29):
     assert 2L ** i >> i == 1L
 
-assert 12L >> 100 == 0
+assert 12L >> 100 == 0
+
+a = 32764L
+s = []
+while a != 0:
+    a, r = divmod(a, 10L)
+    s.append(r)
+
+assert s == [4, 6, 7, 2, 3]