adoping a more efficient division algorithm for bigint. (#232)

* adoping a more efficient division algorithm for bigint.

* add test case.

* modify the implementation to binary search.

* fix type error.

* fix some error.

* remove extra zero.

* add some test cases.

* add some cases

* Update 09_long.py

* Update 09_long.py

---------

Co-authored-by: BLUELOVETH <blueloveTH@foxmail.com>
This commit is contained in:
ykiko 2024-03-29 03:00:39 +08:00 committed by GitHub
parent e86baa2e2f
commit cb15db1f0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 6 deletions

View File

@ -99,11 +99,38 @@ 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)
if ulong_cmp(a, b) < 0:
return [0], a
if len(b) == 1:
q, r = ulong_divmodi(a, b[0])
r, _ = ulong_fromint(r)
return q, r
max = (len(a) - len(b)) * PyLong_SHIFT + \
(a[-1].bit_length() - b[-1].bit_length())
low = [0]
high = (max // PyLong_SHIFT) * [0] + \
[(2**(max % PyLong_SHIFT)) & PyLong_MASK]
while ulong_cmp(low, high) < 0:
ulong_inc_(high)
mid, r = ulong_divmodi(ulong_add(low, high), 2)
if ulong_cmp(a, ulong_mul(b, mid)) >= 0:
low = mid
else:
high = ulong_sub(mid, [1])
q = [0] * (len(a) - len(b) + 1)
while ulong_cmp(a, ulong_mul(b, low)) >= 0:
q = ulong_add(q, low)
a = ulong_sub(a, ulong_mul(b, low))
ulong_unpad_(q)
return q, a
def ulong_floordivi(a: list, b: int):

View File

@ -15,7 +15,6 @@ assert 1 + a == 3L
assert 1 - a == -1L
assert 2 * a == 4L
# __lshift__ and __rshift__
for i in range(29):
assert 1L << i == 2 ** i
@ -36,3 +35,16 @@ assert s == [4, 6, 7, 2, 3]
assert 1 < 2L < 3 < 6.6
assert 1L < 2 < 9.6 >= 7 > 2L
assert 1L < 2 < 3 < 6.6
assert 10000000000000000000000L // 3333L == 3000300030003000300L
assert 10000000000000000000000L % 3333L == 100L
assert 2L ** 100 // 3L ** 50 == 1765780L
assert 2L ** 200 // 3L ** 100 == 3117982410207L
assert 2L ** 500 // 3L ** 200 == 12323863745843010927046405923587284941366070573310012484L
assert 2L ** 500 % 3L ** 200 == 242990057207501525999897657892105676264485903550870122812212566096970021710762636168532352280892L
assert 3L**500 // 3L**400 == 3L**100
assert 4562645248L // 3L == 1520881749L
assert 3L**10 // 2L**200 == 0
assert 2L**500 % 3L**200 == 242990057207501525999897657892105676264485903550870122812212566096970021710762636168532352280892L
assert divmod(10L**115, 3L**47) == (376098003656605353510839433041026531338835641081336270795298342081499446459650747504311257564L, 10150482013473427429132L)