• 补码 符号数的二进制 整数


    Blablabla~ 

    今天重温了《深入了解计算机系统》关于符号数的bianary表示,弄懂了补码的原理。并写了python脚本验证。当初对这块有疑惑是一上来就告诉你,xxx取反加1就是补码,完全不知道为什么这么做,今天抛开这个说法,从我们想要解决问题入手去思考。

    目标

    我们想要解的问题是:我们知道计算机都是binary的存储,那么这些binary怎么解释或者对应到 带符号的整数呢?

    这是我们想要的解决的问题

    解决方案(general)

    提供了一种翻译机制,就是一个函数,输入是binary,输出是 符号数

    def B2S(binary):

          reutrn sign_integer

    具体方案(detail)

    • 一个很正常是思路就是一个bit位符号位,0为正,1为负,其他的n-1 bit照旧。这个方案有一个问题是0有两个表示10000和00000 (这套方案叫 singned magnitude 原码),这个方案正负数相加会有问题哦(不是0)
    • 另外一个思路是负数:保留符号位,其余的数 取反,有一个问题就是+0 = 0000, -0 = 11111,有两个方式(这套方案叫 ones' complement), 两数 x+(-x)会得到1111 (就是-0)
    • 最后看我们计算机中的最终选择的方案吧 (two's complement)

    书里的2.2.3章节的这个图比较形象地画出方案细节,具体可以看下1011的例子。-8在左边是灰色的,蓝色的是正的,累加起来。

    1. def B2U(b):
    2. #binary to unsigned
    3. x=0
    4. b_str = b[::-1]
    5. for i,v in enumerate(b_str):
    6. if int(v)!=0:
    7. x+= np.power(2,i)
    8. return x
    9. def test_B2U():
    10. assert B2U('0001') == 1
    11. assert B2U('0101') == 5
    12. assert B2U('1011') == 11
    13. assert B2U('1111') == 15
    14. def B2T(b):
    15. #bianry to two's component
    16. x = 0
    17. b_str = b[::-1]
    18. idx = len(b_str)-1
    19. for i,v in enumerate(b_str):
    20. if i
    21. if int(v)!=0:
    22. x+= np.power(2,i)
    23. else:
    24. x += -int(v)*np.power(2, i)
    25. return x
    26. def test_B2U():
    27. assert B2U('0001') == 1
    28. assert B2U('0101') == 5
    29. assert B2U('1011') == -5 # -8+2+1
    30. assert B2U('1111') == -1 # -8+4+2+1

    本质上,我们知道符号数的第一位来表示符号,0表示正,1表示负,那么实际的数值就是:

    - 最大的值: 0111, 2^n-1

    - 最小的值: 1000, - 2^n

    - 一般的值:(-v)*2^n+ 其他项

    明白了最小的值是1000,结合上面的图,那么任意bit的整数,-1的表示都是0xfffff。。。

    补码:对于任意x, 我们用 -2^w+x 来表示 -x的w位表示

               另一个思路是,x+(-x)=0 那么,-x = 0-x = 2^w - x = 10000 -(x) 这个思路很好(但是我们不应该记住结论/公式:负数的binary就是其整数取反再加1,记住过程,我们希望x+(-x)=0,所以-x = 0000- x

    总结

    这套方案(函数),在计算机里叫做 "补码编码". 一般都使用补码的形式来表示有符号整数。弄明白了计算机使用补码(two's component)的编码方式来表示负数(即符号数)。本质就是制定一个规则,一个bianry怎么serialze 到有符号数,这个规则就是一个函数,就是我上面写的B2T,这个函数叫做补码编码。

    unsigned char x=0;

    printf("%u", x-1); #255

  • 相关阅读:
    2022 12 3
    C++ 构造函数 explicit 关键字 成员初始化列表
    Java 算法篇-链表的经典算法:根据值删除节点、删除倒数第 n 个节点
    《知识点累积》HTML+JS+CSS
    android.bp文件禁用oat 优化
    烟台个人开发者申请软件著作权的好处
    2023 年最新最全的 React 面试题
    Linux 基础复习
    父子组件通信方式详解
    双指针算法
  • 原文地址:https://blog.csdn.net/Chunying27/article/details/127809494