正整数的补码是其二进制表示,与原码相同。
例:+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
如有帮助到各位,请点赞+收藏+关注,谢谢