Python negative decimal number - code bug ( one number not working )

Hi, been working on a code for the past hours, but on the last hour I have been stuck with this bug:
it works all and good, but when I reached the decimal number -128.
The function wont work. only that number. I realized on my code why it is like that.
The problem is, I cant fix it without changing the whole code, and I dont really have another idea on how to make it work… I will be happy to get tip on how to fix the bug if it is possible.

The Question is:
dec_num (compliment_twos) - the function accepts as number an input in decimal representation and returns as output the
Complements the number 2 in binary representation as a string, in whole byte, with the leftmost bit representing
Is the number negative or not. Note: A positive number with the leftmost (MSB) lit will be completed forever

Sorry for bad translation, not very much good of english of mine + google translate ( it was in hebrew )

def pad_zeros(binary_as_str, length):
    subtraction = length - len(binary_as_str)
    return "0" * subtraction + binary_as_str

def binary_addition(binary_as_str1, binary_as_str2):
    counter , sm_in_string= 0, ""
    if len(binary_as_str1) < len(binary_as_str2):
        binary_as_str1 = pad_zeros(binary_as_str1, len(binary_as_str2))
    elif len(binary_as_str2) < len(binary_as_str1):
        binary_as_str2 = pad_zeros(binary_as_str2, len(binary_as_str1))
    for i in range(len(binary_as_str1) - 1, - 1, - 1):
        if binary_as_str1[i] == "1":
            counter += 1
        if binary_as_str2[i] == "1":
            counter += 1
        sm_in_string = str(counter % 2) + sm_in_string
        if counter >= 2:
            counter = 1
            counter = 0
    if counter % 2 == 1:
        return "1" + sm_in_string
        return sm_in_string

def round_to_zero(binary_as_str):
    counter = 0
    second_counter = 0
    for i in range(8, len(binary_as_str) + 1):
        if len(binary_as_str) < 8:
            return binary_as_str
            if i % 8 == 0:  # 8
                counter += 8
            else:  # 9, 10, 11
                counter += 1
                second_counter += 1  # 1, 2, 3
    rounded = counter + (8 - second_counter)  # 11
    return rounded

def decimal_to_binary(decimal_num):
    binary = ""  # It will increase as the loop continues, will increase by "0" or "1".
    counter = decimal_num  # The decimal number will be decreased with each run.
    while counter != 0:  # If it is equal to zero it means the transformation has ended.
        if counter % 2 == 0:
            counter = counter // 2  # Floor division, e.g: 29.5 goes to 29.
            binary = "0" + binary
            counter = counter // 2  #  Floor division, e.g: 29.5 goes to 29.
            binary = "1" + binary
    if decimal_num == 0:
        binary = "0"
    return binary  # Returns the binary in string after all the process

def twos_compliment(num_dec):
    str1 = ""
    if num_dec > 0:
        binary_in_string = pad_zeros(decimal_to_binary(num_dec), round_to_zero(decimal_to_binary(num_dec))) # 1100100
        for i in range(len(binary_in_string)): # 7-1=6
            if binary_in_string[i] == "0":
                str1 = str1 + "1"
                str1 = str1 + "0"
        str1 = binary_addition(str1, "1")
        decimal = decimal_to_binary(num_dec * (-1))
        length = round_to_zero(decimal_to_binary(num_dec * (-1)))
        return pad_zeros(decimal, length)
    return str1

print(twos_compliment(-128))  # 10000000 - PROBLEM!!
print(twos_compliment(255))  # 1111111100000001
print(twos_compliment(64))  # 11000000
#My Tests:
print(twos_compliment(100))  # 10011100
print(twos_compliment(45))  # 11010011
print(twos_compliment(-45))  # 00101101
print(twos_compliment(-168))  # 0000 0000 1010 1000
print(twos_compliment(-256))  # 0000000100000000
print(twos_compliment(2500))  # 1111011000111100
print(twos_compliment(-127))  # 01111111

[content removed]

I’ve removed this content as I misunderstood the question. As such my input is not relevant.

@ben1122 Sorry about that: just cleaning up your thread.
If I can figure out a solution, I’ll post back.

Hi Thanks, but I know what is negative.
my problem is I have a bug, all negative numbers work, all positive number work.
I need to find the Two Complement string for it.
but the number -128 decimal, wont work, since with my code I get it with 16 bits, but I need to get it to 8bit. thats the problem of my code

To do twos-complement, we start with ones-complement.

In ones-complement, the difference between a positive and negative number is that all the bits are flipped. This only works if we have a fixed number of bits.

So if we have eight bits, the number 107 is:

01101011  # decimal 107 in binary

and negative 107 flips all the bits:

10010100  # decimal -107 in binary ones-complement

So to do ones-complement you need to:

  • Decide on how many bits you are using. You need to do this first.

  • If your number is zero, then the binary is all zeroes.

  • If the number is positive, work out the bits in the usual way. The first bit will be zero, or else your number is out of range.

  • If the number is negative, work out the bits for the positive version, then flip the bits.

So to work out -107 using eight bits, start by working out 107 in binary, which needs seven bits 1101011, pad it to eight bits 01101011, then flip zeroes to ones and ones to zeroes giving 10010100.

To do twos-compement we do exactly the same steps, except that for negative values we add 1 at the end:

So to work out -107 using eight bits:

  • Ignore the negative and convert 107 to binary: 1101011.

  • If it uses more than seven bits your number is out of range.

  • Pad to eight bits: 01101011.

  • Flip the bits to get ones-complement: 10010100.

  • And the extra step is add one: 10010101.

Don’t forget to carry when doing the addition. Here is another example: convert -13104 to twos-complements using 16 bits:

  • Ignore the negative and work out the binary of 13104 as usual: 11001100110000.

  • That’s only 14 bits (less than 16) so it is in range.

  • Pad to 16 bits: 0011001100110000.

  • Flip the bits: 1100110011001111. (Ones-complement.)

  • Add one: 1100110011010000 (twos-complement).

If you think about that for a while, you might spot two issues:

  • There is one value that we wrongly say is out of range.

  • There is a simpler way to get the twos-complement.

Can you see what those two issues are?

Thanks for the huge answer!!!
Really appreciated, I will try to make it to work, i hope atleast :slight_smile:
Just the problem, is that I really did all that was needed.

I used this site and watched the steps.
Thats why I dont get why the code wont work… it seemes good also for all numbers execpt -128
-107 works for me pretty good.

About the issues: I dont see where the first issue? its in range of 16 bits, so its pretty good.
About simpler way, I dont really know, i know there are 2 ways, but actually it was way easier for me, I used the site above to help me.

I’ve tried a few ways, with limited success, based on the XOR operator, but I can’t figure it out: maybe I’m a way off with this approach.

Oh I just solved it, I found a “cheat” way to get minus good,
-128 is like 127
so just did a cheat to get it :slight_smile:

Nice one!

Like I said in my now redacted post: the only difference between -128 and 127 is if the most significant bit is used as a ‘parity bit’, or not.

1 Like

If you want twos-complement of -N, you can:

  • work out ones-complement of N (ignore the minus sign);
  • flip the bits;
  • and then add one.

But that requires writing a function to do binary addition using your
list of zeroes and ones. The easier alternative is:

  • work out ones-complement of N-1 (ignore the minus sign, and subtract one);
  • and flip the bits.

No binary addition needed.

1 Like

Its all good, thanks, I did something similliar to it.
Its solved.
post can be locked if needed :slight_smile:

1 Like

I agree that second way seems -and is- easier than the first one, but isn’t it just too easy to make a “binary addition” function with the help of int(x, base=2) ?(if you already have two special functions: one for decimal to binary converting and one for padding zeroes - the good thing is, we have both as they are required to do twos compliment :slight_smile: )
I have written a short function for that goal:

def bin_add(binary_num, dec_num):
	return pad_zeros( decimal_to_binary(  int( binary_num, base=2 ) + dec_num  ) , len(binary_num) )

which is equal to:

def bin_add(binary_num, dec_num):
    dec_sum = int(binary_num, base=2) + dec_num
    bin_sum = decimal_to_binary(dec_sum)
    return pad_zeros( bin_sum, len(binary_num) )

With the hope of contributing to the topic…

Guys, I already solved it :
Its all good, really.
I did something similliar also, with adding one ( as said before, -128 is like 127 + one digit ).
Thanks anyway :slight_smile:

Oh and about the function, I actually just created a bin_add_one function which is not based on my other function.
I already built one for a different question, so just took it :slight_smile:

1 Like

I’m happy that you have solved your problem, but you don’t own this topic. If people are interested in discussing it further, they can.

You can continue to read and maybe learn something, or not, whichever you prefer.

You can post here freely, i didnt say not.
But i cant comment to each comment. They are pointing at me, i am saying i got it solved but still…
If they are just talking about question, sure, but i dont need to answer for each new comment that tells me of another way ( if i dont answer, its just disrespectful), if they talk in general about question and not to me (op )- go ahead.

Edit:but okay, i will just not answer…