使用两个补码

时间:2018-01-08 07:37:40

标签: python algorithm binary hex twos-complement

正如标题所说,我需要创建一个在2个基础之间转换的函数,DEC和HEX在两个补码中。从一开始就知道值使用的位数。

经过多次挖掘后,我发现了以下算法:

  1. 鉴于DEC中的数字。
  2. 获取数字的绝对值。
  3. 从步骤2获取abs的二进制(BIN)值。
  4. 在左侧填充0 s,直到该数字为所需长度。
  5. NOT在步骤4中获得的所有位。
  6. 在结果中添加1。 (实践中最简单的方法可能是转换回DEC,加1,然后回到BIN)
  7. 转换为HEX。完成。
  8. 这个算法来自我观察者可能只有在原始数字是负数(< 0)时才能工作。通过进行以下修改,我设法得到了看似正确的结果:

    在第6步中,不要添加1.而是添加与原始数字签名相反的内容。例如,如果原始数字为负数,例如-455,则添加1,如果为正数,则为10002,然后添加"添加" -1

    这似乎给出了积极的结果,但我不确定它的健全性,因为在此之前我从未使用过两个补码,而在我看来,对第6步的修改是{{ {1}}。

    这是我提出的Python 3.6函数,DEC值是一个int,所有其他值都表示为字符串,我假设的所需长度只是4的下一个倍数:

    logic + guesswork - formal_knowledge

    至于转换回来,从HEX值转换为DEC值,我设法做了什么"反向工程"(因为我无法找到实际解释的东西):

    1. 给出HEX中的数字。
    2. 以二进制形式表示它,BIN。
    3. 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 填充,直到达到所需的长度。
    4. 检查最左边的位是0(a.k.a。数字是否定的)。
    5. 如果数字是负数,那么将BIN值从步骤3转换为DEC,然后将2减去我们拥有的多个位的幂(1),如果数字不是负数(前导位)是2 ^ len(BIN))然后像往常一样将其转换为DEC。完成。
    6. 这是我为此编写的Python函数(与上面相同的实现细节):

      0

      我的底层问题是:这些函数是否会正确地将任何数字转换为HEX中的两个补码,或者我只是偶然发现幸运测试值的巧合?它是否正确?

      编辑:经过进一步测试,我发现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 并不总是给出正确的值。对于诸如0,1,2等的数字,它给出负值-2,-3,-4等,但对于边界情况,它是有效的-32768和32767。

      由于现在显然不正确,我应该更改(对于两种算法)以便它们是正确的?

      提前谢谢!

1 个答案:

答案 0 :(得分:1)

  

我的底层问题是:这些函数会正确地将任何数字转换为HEX中的两个补码,还是我偶然发现幸运测试值的巧合?这是对的吗?

您正在将每个数字(正数和负数)转换为其二进制补码表示。你应该只为负数做这个。这就是它们的表示方式,即使用其绝对值的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位等。并将所有输入转换为二进制的多个位。