更新时间:2022-12-09 17:25:21
此解决方案使用基本的位移位和位提取.使用位运算应比使用幂运算和乘运算等更高级别的运算更快.
This solution uses basic bit shifting and bit extraction. Using bit operations should be faster than using higher level operations such as exponentiation and multiplication.
基本解决方案与特殊情况非常相似,因为在任何一种情况下都只需要一个整数的最大位长.但是,测试不是.
The fundamental solution is much the same as in the special case, since only one integer's maximum bit length is required in either case. The tests, however, are not.
from typing import Tuple
import unittest
class IntMerger:
"""Reversibly encode two integers into a single integer.
Only the first integer can be signed (possibly negative). The second
integer must be unsigned (always non-negative).
In the merged integer, the left bits are of the first input integer, and
the right bits are of the second input integer.
"""
# Ref: https://***.com/a/54164324/
def __init__(self, num_bits_int2: int):
"""
:param num_bits_int2: Max bit length of second integer.
"""
self._num_bits_int2: int = num_bits_int2
self._max_int2: int = self._max_int(self._num_bits_int2)
@staticmethod
def _max_int(num_bits: int) -> int:
return (1 << num_bits) - 1
def merge(self, int1: int, int2: int) -> int:
return (int1 << self._num_bits_int2) | int2
def split(self, int12: int) -> Tuple[int, int]:
int1 = int12 >> self._num_bits_int2
int2 = int12 & self._max_int2
return int1, int2
class TestIntMerger(unittest.TestCase):
def test_intmerger(self):
max_num_bits = 8
for num_bits_int1 in range(max_num_bits + 1):
for num_bits_int2 in range(max_num_bits + 1):
expected_merged_max_num_bits = num_bits_int1 + num_bits_int2
merger = IntMerger(num_bits_int2)
maxint1 = (+1 << num_bits_int1) - 1
minint1 = (-1 << num_bits_int1) + 1
for int1 in range(minint1, maxint1 + 1):
for int2 in range(1 << num_bits_int2):
int12 = merger.merge(int1, int2)
# print(f'{int1} ({num_bits_int1}b), {int2} ({num_bits_int2}b) = {int12} ({int12.bit_length()}b)')
self.assertLessEqual(int12.bit_length(), expected_merged_max_num_bits)
self.assertEqual((int1, int2), merger.split(int12))
self.assertEqual(int12.bit_length(), expected_merged_max_num_bits)
if __name__ == '__main__':
unittest.main()
用法示例:
>>> merger = IntMerger(12)
>>> merger.merge(13, 8)
53256
>>> merger.split(_)
(13, 8)
>>> merger.merge(-13, 8)
-53240
>>> merger.split(_)
(-13, 8)