正如标题所说,我需要创建一个函数,该函数在两个碱基(DEC 和 HEX )之间进行二进制补码之间的转换。值使用的位数从一开始就是已知的。
在做了更多的挖掘之后,我发现了以下算法:
- 在DEC中给出一个数字。
- 获取数字的绝对值。
- 获取步骤 2 中 abs 的二进制 (BIN) 值。 在
- 左侧用
0
s 填充,直到数字达到所需的长度。 NOT
步骤4中获得的所有位。- 将结果加 1。(实践中最简单的方法可能是转换回 DEC,加 1,然后转换回 BIN)
- 转换为十六进制。做。
我观察到的这种算法可能仅在原始数字为负数(<0)时才有效。通过进行以下修改,我设法获得了看似正确的结果:
在步骤 6 中,不要添加 1。而是添加与原始数字签名相反的内容。例如,如果原始数字为负数,如-455
则加1
,如果为正数,如10002
则"加"-1
。
这似乎确实给出了积极的结果,但我不确定它的合理性,因为在此之前我从未使用过两个补码,而且在我看来,对步骤 6 的修改logic + guesswork - formal_knowledge
。
这是我想出的 Python 3.6 函数,DEC 值是一个 int,所有其他值都表示为字符串,我假设所需的长度只是 4 的下一个倍数:
def d2h(i: int) -> str:
sign = (i // abs(i)) if i is not 0 else 1
step1 = i
step2 = abs(step1)
step3 = bin(step2)[2:]
step4 = step3
while len(step4) % 4 != 0:
step4 = '0' + step4
step5 = step4.replace('0', 'O')
.replace('1', '0')
.replace('O', '1')
step6 = bin(int(step5, 2) + -sign)[2:]
step7 = hex(int(step6, 2))[2:]
return step7
至于从十六进制值转换回DEC值,我设法进行了"逆向工程"(因为我无法找到实际解释这一点的东西):
- 给定一个十六进制数字。
- 获取二进制 BIN 中的表示形式。
- 用
0
填充直到所需的长度。 - 检查最左边的位是否
1
(即数字为负数)。 - 如果数字为负数,则将步骤 3 的 BIN 值转换为 DEC,然后将 2 减去我们拥有的多少位的幂(
2 ^ len(BIN)
),如果数字不是负数(前导位为0
),则只需像往常一样将其转换为 DEC。做。
这是我为此编写的 Python 函数(与上面的实现细节相同):
def h2d(h: str) -> int:
step1 = h
step2 = bin(int(h, 16))[2:]
step3 = step2
while len(step3) % 4 != 0:
step3 = '0' + step3
if step3[0] == '1':
step4 = int(step3, 2) - (2**len(step3))
else:
step4 = int(step3, 2)
return step4
我最底层的问题是:这些函数是否会在十六进制中正确地将任何数字转换为 2 的补码,或者我只是偶然发现了幸运测试值的巧合? 这是对的吗?
编辑:经过进一步测试,我发现h2d(d2h())
并不总是给出正确的值。对于 0、1、2 等数字,它给出负值 -2、-3、-4 等,但对于边界情况,-32768 和 32767 它有效。
由于现在显然不正确,我应该更改什么(对于两种算法)才能使它们正确?
提前谢谢你!
我的基本问题是:这些函数是否会在十六进制中正确地将任何数字转换为 2 的补码,或者我只是偶然发现了幸运测试值的巧合?这是对的吗?
您正在将每个数字(正数和负数)转换为其二进制补码表示。您应该只对负数执行此操作。这就是它们的表示方式,即使用其绝对值的 2s 补码。所以你的 d2h 函数变成:
def d2h(i: int) -> str:
sign = (i // abs(i)) if i is not 0 else 1
step1 = i
step2 = abs(step1)
step3 = bin(step2)[2:]
step4 = step3
while len(step4) % 4 != 0:
step4 = '0' + step4
if sign == -1:
step5 = step4.replace('0', 'O')
.replace('1', '0')
.replace('O', '1')
step6 = bin(int(step5, 2) + 1)[2:]
else:
step5 = step4
step6 = step5
step7 = hex(int(step6, 2))[2:]
return step7
此外,您必须决定应该使用多少位来表示数字,例如 32 位、64 位等。并将所有输入转换为二进制中的多位。