我想将两个可能具有不同最大位长的大整数编码为一个整数。第一个整数是有符号的(可以是负数),而第二个是无符号的(总是非负数)。如果位长分别为m
和n
,则返回整数的位长应小于或等于m + n
。
n
(而不是m
)是预先已知的并且是固定的。作为示例,将使用该解决方案将61+位的带符号nanosecond timestamp与256位的无符号随机性组合在一起,以形成一个317+位的带符号唯一标识符。
我正在使用最新的Python。 special case when m == n
中有一个相关的先前存在的问题可以解决这个问题。
答案 0 :(得分:2)
因为 n 是固定的,所以这个问题很简单:将( a , b )编码为 a • 2 n + b 。
如果 m 和 n 不固定,则该问题是不可能的,因为它要求我们同时对这两者进行编码(两位 a 位( b )和(一位 a ,两位 b )分成三位,这意味着我们必须对十二种可能进行编码( 0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,2),(1,3),(2,三个位的八个组合中的0),(2,1),(3,0)和(3,1),这是不可能的。
答案 1 :(得分:0)
此解决方案使用基本的位移位和位提取。使用位运算应比使用指数运算和乘法等更高级别的运算更快。
基本解决方案与特殊情况非常相似,因为在任何一种情况下都只需要一个整数的最大位长。但是,测试不是。
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://stackoverflow.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)
答案 2 :(得分:0)
如果您绝对必须具有完全的可逆性,则需要放松至少一个隐含的初始条件(因为如果您不分别记住这些数字中的任何一个,并且响应位长R小于m + n,您只是不可挽回地丧失了全部可逆性):