Python实现十进制数与二进制补码转换

Python实现十进制数与二进制补码转换

二进制补码(BNR)

正数

正整数的补码是其二进制表示,与原码相同。

例:+9的补码是00001001。(备注:这个+9的补码是用8位2进制来表示的,补码表示方式很多,还有16位二进制补码表示形式,以及32位二进制补码表示形式,64位进制补码表示形式等。每一种补码表示形式都只能表示有限的数字。)

负数

求负整数的补码,将其原码除符号位外的所有位取反(0变1,1变0,符号位为1不变)后加1。

同一个数字在不同的补码表示形式中是不同的。比如-15的补码,在8位二进制中11110001,然而在16位二进制补码表示中,就是1111111111110001。以下都使用8位2进制来表示。

例:求-5的补码。

-5对应带符号位负数5(10000101)→除符号位外所有位取反(11111010)→加 00000001为 (11111011)所以-5的补码是11111011

示例代码

def dec2bnr(dec: int, lenth: int = 19) -> str:
    """十进制数转指定长度二进制补码(BNR)

    Args:
        dec (int): 十进制数
        lenth (int, optional): 指定长度(正数高位补0,负数高位补1). Defaults to 19.

    Raises:
        TypeError: 输入非十进制整数!
        OverflowError: 输入十进制整数过大,超过指定补码长度

    Returns:
        str: 返回二进制补码字符串
    """

    if not isinstance(dec, int):
        raise TypeError("输入非十进制整数!")

    # 计算十进制转化为二进制后的位数
    digits = (len(bin(dec)) - 3) if dec < 0 else (len(bin(dec)) - 2)

    if digits >= lenth:
        raise OverflowError("输入十进制整数过大,超过指定补码长度")

    # Note: dec & 相同位数的0b111...强制转换为补码形式
    pattern = f"{dec & int('0b' + '1' * lenth, 2):0{lenth}b}"

    return ",".join(code for code in pattern)
def bnr2dec(data: str) -> int:
    """二进制补码(BNR)转十进制数

    Args:
        data (str): 二进制补码字符串,如"100101100"

    Raises:
        TypeError: 输入非字符串!
        ValueError: 输入非二进制字符串!

    Returns:
        int: 十进制数
    """

    if not isinstance(data, str):
        raise TypeError("输入非字符串!")

    for num in data:
        if num not in ["0", "1"]:
            raise ValueError("输入非二进制字符串!")

    # 正整数原码与补码相同
    if data.startswith("0"):
        dec = int(data, 2)
    else:
        # 补码-->反码-->原码
        dec = int(data[1:], 2) - 0x01
        dec = -(~dec & int("0b" + "1" * (len(data) - 1), 2))

        # Note: 整数在计算机中以补码的形式存储,所以按位取反运算符(~)会将补码的符号位也取反,故用&运算符清零特性(任何数与0相与都为0,与1相与保持不变)
        #       即dec & 0b1111...(位数取决于dec的位数),0b1111在计算机中的存储的补码为01111,dec与之相与后符号位被清零,即可实现非计算机层面的按位取反

    return dec

单元测试

def test_dec2bnr() -> None:
    """测试十进制整数转指定长度二进制补码"""
    with pytest.raises(TypeError):
        dec2bnr("128")

    with pytest.raises(OverflowError):
        dec2bnr(128, 6)

    assert dec2bnr(144, 14) == "0,0,0,0,0,0,1,0,0,1,0,0,0,0"
    assert dec2bnr(-2022) == "1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,0,1,0"
def test_bnr2dec() -> None:
    """测试二进制补码转十进制数"""
    with pytest.raises(TypeError):
        bnr2dec(10010)

    with pytest.raises(ValueError):
        bnr2dec("s10010")

    assert bnr2dec("0000011111100110") == 2022
    assert bnr2dec("1111100000110010") == -1998

如有帮助到各位,请点赞+收藏+关注,谢谢

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在计算机中,值表示通常使用二进制,而为了进行运算和存储,我们需要不同的制表示形式:原码、反码和补码。这些方法主要应用于有符号整,特别是对于负的表示。 **1. 原码(Unsigned):** - 对于正,原码就是它的二进制表示。 - 对于负,原码是在最高位(符号位)为1的情况下,剩下的不变。 例如,十进制-5的原码在二进制中是 `10000101`。因为最高位是1,表示负。 **2. 反码(One's Complement):** - 正的反码是其对应的原码。 - 负的反码是其原码逐位取反(包括符号位),然后加1。 例如,-5的反码是 `11111010`,因为原码是 `10000101`,取反后得到 `01111011`,加1得 `11111010`。 **3. 补码(Two's Complement):** - 补码是计算机中最常用的表示负的方法。 - 正补码等于其原码。 - 负补码是其反码加1。 同样,-5的补码是 `11111010`,因为反码 `11111010` 加1等于 `11111011`。 以下是简单的Python代码示例,用于将十进制转换为这三种表示: ```python def convert_to_binary(num, mode='decimal'): if mode == 'decimal': return format(int(num), '08b') elif mode == 'unsigned': return bin(num)[2:] elif mode == 'ones_complement': return format(~int(num), '08b') elif mode == 'two_complement': return format(int(num) & ~1, '08b') # 使用补码规则 # 示例 decimal_num = 5 print("十进制:", convert_to_binary(decimal_num)) print("原码:", convert_to_binary(decimal_num, 'unsigned')) print("反码:", convert_to_binary(decimal_num, 'ones_complement')) print("补码:", convert_to_binary(decimal_num, 'two_complement')) ``` 如果你对这些概念或代码有任何疑问,请告诉我,我会进一步解释或者提供相关的问题供你深入学习。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值