python - 正负分数到二进制的转换

标签 python python-3.x binary fractions

我正在尝试将正分数和负分数转换为二进制,我在网上找到了以下方法( https://www.geeksforgeeks.org/convert-decimal-fraction-binary-number/ )将正分数转换为二进制,并尝试扩展它以支持负分数。 我正在尝试对小数部分进行 2 的补码。非常感谢任何帮助。

# decimal to binary number

# Function to convert decimal to binary
# upto k-precision after decimal point
def decimalToBinary(num, k_prec) :

    binary = ""

    # Fetch the integral part of
    # decimal number
    Integral = int(num)

    # Fetch the fractional part
    # decimal number
    fractional = num - Integral

    # Conversion of integral part to
    # binary equivalent
    while (Integral) :
        
        rem = Integral % 2

        # Append 0 in binary
        binary += str(rem);

        Integral //= 2
    
    # Reverse string to get original
    # binary equivalent
    binary = binary[ : : -1]

    # Append point before conversion
    # of fractional part
    binary += '.'

    # Conversion of fractional part
    # to binary equivalent
    while (k_prec) :
        
        # Find next bit in fraction
        fractional *= 2
        fract_bit = int(fractional)

        if (fract_bit == 1) :
            
            fractional -= fract_bit
            binary += '1'
            
        else :
            binary += '0'

        k_prec -= 1

    if (num < 0): # if negative numbers do the two's complement
        binary = ~binary # struck here.
    else:
        binary = binary
    return binary

# Driver code
if __name__ == "__main__" :
    num_list=[1, 0, 0.924, -0.383]
    for i in num_list:
        print(i, decimalToBinary(i,8))
macky@test:~/test$ python frac_to_binary.py 
(1, '1.00000000')
(0, '.00000000')
(0.924, '.11101100')
Traceback (most recent call last):
  File "frac_to_binary.py", line 63, in <module>
    print(i, decimalToBinary(i,8))
  File "frac_to_binary.py", line 54, in decimalToBinary
    binary = ~binary
TypeError: bad operand type for unary ~: 'str'

最佳答案

实际上有几种方法可以将二进制数显示为负数。需要记住的重要一点是注意你的位大小;将您的位大小设置为大于您要转换的最大值,否则可能会发生奇怪的事情:

  • 数字的位 = 4 <= 7 ( 0111 )
  • 数字的位 = 5 <= 15 ( 01111 )
  • 数字的位 = 8 <= 127 ( 01111111 )

要记住的另一件事是,您必须转换整个二进制表示形式,而不是每个部分。

我修改了您的函数以显示四种类型的表示形式:有符号符号大小一个补码两个补码:

NOTE - Tested on CentOS 7.9, using Python 2.7, and on Ubuntu 20.04, using Python 3.8

"""Program to convert rational numbers to signed and unsigned binary representations
Signed: Add a sign (0001 = 1, -0001 = -1)
Sign Magnitude: The sign is the most significant bit (0001 = 1, 1001 = -1)
One's Complement: Flip all the bits to their opposite value (0001 = 1, 1110 = -1)
Two's Complement: Flip all the bits, then add 1 to the least significant bit (0001 = 1, 1111 = -1)

Signed and decimal values checked at
    https://www.rapidtables.com/convert/number/binary-to-decimal.html
Complements checked at https://planetcalc.com/747/

Warning: Set your bit size larger than the max value that you want to convert:
bits = 4 for numbers <= 7 (0111)
bits = 5 for numbers <= 15 (01111)
...
bits = 8 for numbers <= 127 (01111111)
"""


def decimal_to_binary(num, bits):
    """Function to convert rational numbers to binary representations

    :param float num: The decimal to convert to binary
    :param int bits: The bit size; see warning in the module docstring
    :return: A formatted string with Signed, Sign Mag, One's Comp, and Two's Comp representations
    :rtype: str
    """
    # Ensure the number is a float
    num *= 1.0

    # Separate the number's components
    whole_part = int(str(num).split(".")[0])
    decimal_part = float("." + str(num).split(".")[1])

    # Convert the whole part to binary
    if whole_part >= 0:
        whole_binary = format(whole_part, "0{0}b".format(bits))
    else:
        # Remove the sign
        whole_binary = format(whole_part * -1, "0{0}b".format(bits))

    # Convert the decimal part to binary
    k_prec = bits
    if decimal_part == 0:
        decimal_binary = format(0, "0{0}b".format(k_prec))
    else:
        db_list = []
        while k_prec > 0:
            decimal_part *= 2
            db_list.append(int(decimal_part))
            decimal_part -= int(decimal_part)
            k_prec -= 1
        decimal_binary = ''.join(str(d) for d in db_list)

    # Put the binary representations back together and sign (for Signed and Sign Magnitude)
    binary = whole_binary + "." + decimal_binary
    mag_binary = "0" + binary[1:] if num >= 0 else "1" + binary[1:]
    signed_binary = binary if num >= 0 else "-" + binary

    if num >= 0:
        ones_binary = "n/a"
        twos_binary = ""
    else:
        # Create an unsigned binary representation (for Complements)
        raw_binary = whole_binary + decimal_binary
        ones_binary = ""
        # Flip bits; as chepner says, ~ doesn't work on strings
        for c in raw_binary:
            ones_binary += '1' if c == '0' else '0'
        # Add 1 to the least significant digit
        twos_binary = bin(int(ones_binary, 2) + 1)
        # Format for display
        ones_binary = ones_binary.replace("0b", "")
        ones_binary = ones_binary[:bits] + "." + ones_binary[bits:]
        twos_binary = twos_binary.replace("0b", "")
        twos_binary = twos_binary[:bits] + "." + twos_binary[bits:]

    return "{0:>8}\t{1:>10}\t{2}\t{3}\t{4}".format(
        num, signed_binary, mag_binary, ones_binary, twos_binary)


def main():
    # I am using 4 bits for readability, so I am keeping the numbers below 7
    num_list = [1, 0, 0.924, -0.383, -0.5, -1, ]
    print("Original\t Signed\t    Sign Mag\tOne's Comp\tTwo's Comp")
    for i in num_list:
        print(decimal_to_binary(i, 4))


if __name__ == "__main__":
    main()

输出:

Original     Signed     Sign Mag    One's Comp  Two's Comp
     1.0     0001.0000  0001.0000   n/a 
     0.0     0000.0000  0000.0000   n/a 
   0.924     0000.1110  0000.1110   n/a 
  -0.383    -0000.0110  1000.0110   1111.1001   1111.1010
    -0.5    -0000.1000  1000.1000   1111.0111   1111.1000
    -1.0    -0001.0000  1001.0000   1110.1111   1111.0000

我使用 RapidTables' Binary to Decimal converter 测试了结果和 PlanetCalc's One's complement, and two's complement binary codes calculator .

如果我有更多时间,我会将其分解为单独的功能并简化一些事情,但我将其留给您。祝你的代码好运!

关于python - 正负分数到二进制的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70114029/

相关文章:

python - 如何在 Python 3 中使用 pyhocon 动态生成 Hocon conf 文件?

r - 基于间隔和两个变量 - 年龄类别创建二元变量

python - 当 QuerySet 加载实例时,Django 会发送信号 pre_init/post_init 吗?

python - 查找模式时出现无法散列的类型错误

python - 如何打印 'X' 字符序列中的每 5 个字符?

Python 在进程列表中检测 python 脚本的名称

c - 二进制文件读取,将2个字节转换为一个unsigned short C

c - 如何判断C输入是否为8位二进制数

python - 符号 "#!"在 Python 中是什么意思?

使用 while 循环从输入中获取 Python 函数子列表