使用 2 的补码在 DEC(基数 10)和十六进制(基数 16)之间进行转换



正如标题所说,我需要创建一个函数,该函数在两个碱基(DEC 和 HEX )之间进行二进制补码之间的转换。值使用的位数从一开始就是已知的。

在做了更多的挖掘之后,我发现了以下算法:

  1. 在DEC中给出一个数字。
  2. 获取数字的绝对值。
  3. 获取步骤 2 中 abs 的二进制 (BIN) 值。
  4. 左侧用0s 填充,直到数字达到所需的长度。
  5. NOT步骤4中获得的所有位。
  6. 将结果加 1。(实践中最简单的方法可能是转换回 DEC,加 1,然后转换回 BIN)
  7. 转换为十六进制。做。

我观察到的这种算法可能仅在原始数字为负数(<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值,我设法进行了"逆向工程"(因为我无法找到实际解释这一点的东西):

  1. 给定一个十六进制数字。
  2. 获取二进制 BIN 中的表示形式。
  3. 0填充直到所需的长度。
  4. 检查最左边的位是否1(即数字为负数)。
  5. 如果数字为负数,则将步骤 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 位等。并将所有输入转换为二进制中的多位。

最新更新