import unittest max_digit = 2**31 - 1 def lil_divmod(A, B): ''' Return the greatest digit in 1..max_digit such that B * digit <= A and the remainder A - B * digit. ''' assert A > 0 and B > 0 assert A >= B assert B * (max_digit + 1) > A digit = max_digit Q = digit * B while Q > A: digit >>= 1 if not digit: raise ValueError('huh?') Q = digit * B if max_digit == digit: return digit, A - Q remainder = A - Q if remainder < B: return digit, remainder # if remainder >= B the interval to search is # range(digit + 1, digit << 1), eh? low, high = digit + 1, digit << 1 range_ = high - low print(f'{digit + 1}..{digit << 1} = {range_}') if range_ < 8190: while remainder >= B: digit += 1 remainder -= B else: 1/0 return digit, remainder def find_greatest(low, high, f): ''' Return the highest number n: low <= n <= high for which f(n) and not f(n+1) is True. The greatest n which makes f(n) True. ''' assert low <= high # Maybe the high number is already the one? if f(high): return high # No such luck, let's pick a number between low and high pivot = (low + high) >> 1 #print(low, pivot, high) # If there isn't any such number in between low and high, # that means there's only two numbers it could be: low or high # and we already know it isn't high from the test above # so it must be low. if low == pivot: assert f(low) and not f(low + 1) return low assert low < pivot < high return ( find_greatest(pivot, high - 1, f) if f(pivot) else find_greatest(low, pivot - 1, f) ) class find_greatest_Test(unittest.TestCase): def test_find_greatest(self): k = 23300 a = 1 b = 2**31-1 f = lambda n: n <= k n = find_greatest(a, b, f) self.assertEqual(n, k) ##class BigIntTest(unittest.TestCase): ## ## def test_to_int(self): ## a = 10*max_digit-3 ## b = 123 ## a = (max_digit-3) * b ## digit, remainder = lil_divmod(a, b) ## #print(f'divmod({a}, {b}) == ({digit}, {remainder}) # ? ') ## self.assertEqual((digit, remainder), divmod(a, b)) if __name__ == '__main__': unittest.main()