1
votes

As the title says I need to make a function that converts between the 2 bases, DEC and HEX in twos complement. The number of bits the value uses is known from the start.

After doing more than a little digging around i found the following algorithm:

  1. Given a number in DEC.
  2. Get the absolute value of the number.
  3. Get the binary(BIN) value of the abs from step 2.
  4. Pad with 0s on the left until the number is the desired length.
  5. NOT all the bits obtained in step 4.
  6. Add 1 to the result. (Easiest way in practice is probably to convert back to DEC, add 1, and back to BIN)
  7. Convert to HEX. Done.

This algorithm from what I observer might only work if the original number is negative(<0). I managed to get results that seem correct by making the following modification:

On step 6, don't add 1. Instead add the opposite of the signature of the original number. For example if the original number was negative, like -455 then add 1, if it was positive, like 10002 then "add" -1.

This does seem to give positive results but I'm not sure about it's soundness as I have never worked with two's complement before this and this modification to step 6 was in my view logic + guesswork - formal_knowledge.

Here is the Python 3.6 function I came up with, the DEC value is an int, all other values are represented as strings, the desired length i assumed was just the next multiple of 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

As for converting back, from a HEX value to a DEC one, what I managed to kind of "reverse engineer"(as I was not able to find something that actually explained this):

  1. Given a number in HEX.
  2. Get it's representation in binary, BIN.
  3. Pad with 0 until the desired length.
  4. Check if the leftmost bit is 1(a.k.a. the number is negative).
  5. If the number is negative, then convert the BIN value from step 3 to DEC and then subtract 2 to the power of however many bits we have( 2 ^ len(BIN) ), if the number is NOT negative(the leading bit is 0) then simply convert it to DEC like usual. Done.

Here is the Python function I wrote for that(same implementation details as above):

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

My bottom question is: Will these functions convert any number to and from two's complement in HEX correctly or did I just stumble into a coincidence of lucky test values? Is this correct?

EDIT: Upon further testing I have found that h2d(d2h()) does not always give the correct values. For numbers such as 0, 1, 2, etc. it gives the negative values -2, -3, -4, etc. but for the border cases, -32768 and 32767 it works.

Since it is obviously incorrect now, what should I change(for both algorithms) so that they would be correct?

Thank you in advance!

1
have many even odd positive negative zero min and max numbers have you tried? - ShpielMeister
Are your test values -455 and 10002? Edit the question. - Peter Wood
@ShpielMeister I have edited the question. - Rares Dima
@PeterWood I have edited the question, sadly apparently it is not correct. - Rares Dima

1 Answers

1
votes

My bottom question is: Will these functions convert any number to and from two's complement in HEX correctly or did I just stumble into a coincidence of lucky test values? Is this correct?

You are converting every number (both positive and negative) to its two's complement representation. You should only do this for negative numbers. That's how they are represented i.e. using 2s complement of their absolute values. So your d2h function becomes:

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

Additionally, you have to decide upon how many bits you should be using to represent the numbers, eg. 32 bits, 64 bits etc. And convert all your inputs to that many bits in binary.