0

I've made a really simple decimal to binary converter, everything seems to work fine but when given a big number it spits out results that are way different from results from another online converters. I wonder why is that?

here's my code:

def main():
    numberstr = input("Number in decimal > ")
    number = int(numberstr)
    result = ""
    while number >= 1 == True:
        if (number % 2) == 1:
            remainder = "1"
            result = remainder + result
            if number == 1:
                number = 0
            else:
                number = number - 1
                number = number / 2
                number = int(number) 
                #^^^ this line is for getting rid of the float that comes from dividing.

        elif (number % 2) == 0:
            remainder = "0"
            result = remainder + result
            number = number / 2
            number = int(number)
        
    print(numberstr, "in binary is:", result)
  
main()

for example feeding it this number: 987654321987654321
gives out this result: 110110110100110110100101111101111110111101000001001010000001
While online converters (namely rapidtables.com and binaryhexconverter.com ) both give out this: 110110110100110110100101111101111110111101000001001010110001

For comparing:
110110110100110110100101111101111110111101000001001010000001 - my code
110110110100110110100101111101111110111101000001001010110001
It seems that to some point it does the math right, but then it messes up for some reason.
Any ideas on what might be causing it?

SpizCode
  • 3
  • 2
  • There's no need for `== True:`. Just write `while number >= 1:` – Barmar Oct 04 '22 at 21:00
  • You can use `number = number // 2` to do integer division. Then you don't have to subtract 1 or call `int()`. – Barmar Oct 04 '22 at 21:02
  • Welcome to Stack Overflow. Please read [ask] and try to [understand carefully what the code is actually doing](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) before asking for help finding a problem. – Karl Knechtel Oct 04 '22 at 21:09
  • I assume this is an exercise, since in Python `format(987654321987654321,'b')` gives the same answer. – Mark Tolonen Oct 04 '22 at 21:26

1 Answers1

0

The issue is with division. When you do number / 2 it becomes a float. When you are working with large numbers, floats will loose precision.

You need to use floor division number // 2, which gives the quotient of number divided by 2, discarding the remainder. Once you use floor division or integer division, you no longer need number=number - 1, or number = int(number).

def main():
    numberstr = input("Number in decimal > ")
    number = int(numberstr)
    result = ""
    while number >= 1 == True:
        if (number % 2) == 1:
            remainder = "1"
            result = remainder + result
            if number == 1:
                number = 0
            else:
                number = number // 2
                #^^^ this line is for getting rid of the float that comes from dividing.

        elif (number % 2) == 0:
            remainder = "0"
            result = remainder + result
            number = number // 2
        
    print(numberstr, "in binary is:", result)
  
main()

This will give you the correct result:

110110110100110110100101111101111110111101000001001010110001

Alternatively,

Another good way of doing integer division by 2, i.e. discard the last binary digit, is to use bit shift operator >>, this shifts the binary representation to the right by 1 bit and thus removing the last bit, whether it's 0 or 1.

number = number >> 1

And to get the remainder, another good way is "bitwise and" operator &:

remainder_number = number & 1

Bitwise operations are fast.

So a much shorter version would be

def main():
    numberstr = input("Number in decimal > ")
    number = int(numberstr)
    result = ""
    while number >= 1:
        result = str(number & 1) + result
        number = number >> 1

    print(numberstr, "in binary is:", result)

main()

if-else statements are also slow, avoid them if you can.

Tim
  • 3,178
  • 1
  • 13
  • 26