Search code examples
pythonbinarynumbersconverters

Base 10 to Base 2 Conversion with large integers in python


I'm working on a number converter in python and am finding it difficult to correctly convert large decimal values (larger than 2^53) from decimal to binary. I have done many random tests to find the breaking point but I'm not sure why it is breaking. I thought Python 3 allowed for arbitrarily large numbers. I might be losing some data converting between str and int values. Thank you for your help. Here is the code I am using:

# @param: num is an integer >= 0 
# @return: A string containing the converted binary value of num 
def base10to2(num):
    if(not bool(re.match(decimals, str(num)))):
        return "num must be a decimal number string [0-9]."
    if(int(num) <= 1):
        return num
    binaryValue = ''
    decimalRemainder = int(num)
    while decimalRemainder > 0:
        binaryValue = str(decimalRemainder % 2) + binaryValue
        decimalRemainder = math.floor(decimalRemainder / 2)    
    return binaryValue

Here are some of my random test results:

error bin <--> dec at decimal value 57578088768095921 and binary value 11001100100011101111011101110111110111100100011010110000. 11001100 10001110 11110111 01110111 11011110 01000110 10110001 should be 11001100 10001110 11110111 01110111 11011110 01000110 10110000

error bin <--> dec at decimal value 94158773465990610 and binary value 101001110100001001110011111010100111011010100010111010000. 101001110100001001110011111010100111011010100010111010010 should be 101001110100001001110011111010100111011010100010111010000

error bin <--> dec at decimal value 27741136442133437 and binary value 1100010100011100110101010100111010011001000101110111100. 1100010100011100110101010100111010011001000101110111100 should be 1100010100011100110101010100111010011001000101110111101

error bin <--> dec at decimal value 102400897160966081 and binary value 101101011110011010001001011001011111101011110111111000000. 101101011110011010001001011001011111101011110111111000000 should be 101101011110011010001001011001011111101011110111111000001

error bin <--> dec at decimal value 61449679276206615 and binary value 11011010010100000010100001100000110100011110101000011000. 11011010010100000010100001100000110100011110101000011000 should be 11011010010100000010100001100000110100011110101000010111

error bin <--> dec at decimal value 32630026885393859 and binary value 1110011111011001101011000101001100000111110110111000100. 111 0011 1110 1100 1101 0110 0010 1001 1000 0011 1110 1101 1100 0100 should be 0011 1110 1100 1101 0110 0010 1001 1000 0011 1110 1101 1100 0011

error bin <--> dec at decimal value 28823706477206651 and binary value 1100110011001110000001000100001101011110001110001111100. 1100110 01100111 00000010 00100001 10101111 00011100 01111100 should be 1100110 01100111 00000010 00100001 10101111 00011100 01111011

error bin <--> dec at decimal value 32300284354028835 and binary value 1110010110000001110111111111111000100001110010100100100. 1110010 11000000 11101111 11111111 00010000 11100101 00100100 should be 1110010 11000000 11101111 11111111 00010000 11100101 00100011

error bin <--> dec at decimal value 15026178163056103 and binary value 110101011000100011101010111011101111011001110111101001. 110101 01100010 00111010 10111011 10111101 10011101 11101001 should be 110101 01100010 00111010 10111011 10111101 10011101 11100111

It seems only the last 4 bits are incorrect in these cases.

Here is the procedure to convert from base 2 to base 10 I have (just in case this is relevant).

# @param: num is binary whole number
# @return: A string containing the converted decimal value of num
def base2to10(num):
    if(not bool(re.match(binary, str(num)))):
        return "num must be a binary number string [0-1]."
    digits = []
    placeValue = 1
    decimalValue = 0
    digits = list(num)
    for i in range(len(digits)):
        decimalValue += placeValue * int(digits[len(digits) - i - 1])
        placeValue *= 2
    return decimalValue

Solution

  • This:

    decimalRemainder = math.floor(decimalRemainder / 2)
    

    introduces inaccuracy into your calculation, because you are performing float division, which is only approximate, because floats have limited precision.

    Instead you can use

    decimalRemainder = decimalRemainder // 2
    

    which performs the division with ints and is precise.

    With that change, base10to2(94158773465990610) gives '101001110100001001110011111010100111011010100010111010010', which is correct.

    See also the built-in bin function.