很简单的shabby问题

C/C++带来的^运算符的问题

*************************************************************************************************************************************************

C/C++中的“^”是指平方,如2^3 = 8

Java中的“^”是指异或运算符,2^3 = 00...010^00...011 = 00...001 = 1

不要混淆,特别是在刷题中,Java要使用平方可以乘2次,如:x*x,也

可以使用 public static double pow(double a, double b)方法。

 

 

32位机器寻址能力:4GB

*************************************************************************************************************************************************

 

计算误区:2^32  =  2^22 * 2^10= 2^22Gb = 2^14 * 2^8 * Gb = 2^14 GB

原因:不知道你为什么直接就有:G = 2^10b 

实际上:k = 2^10,M = 1024 * k = 2^20,G = 1024 * M = 2^30

所以,2^32 = 4* 2^30 = 4 G

那么B是哪里来的???

还是说已经规定了内存是按字节(B)编址的了?

 

 

计算机中负数补码为原码+1【1】

*************************************************************************************************************************************************

eg 16位机器中:

正数三码合一:
5 的原码:0000 0000 0000 0101
5 的反码:0000 0000 0000 0101
5 的补码:0000 0000 0000 0101 

负数有区别:
-3 的原码:1000 0000 0000 0011    
-3 的反码:1111 1111 1111 1100    //注意符号位不变
-3 的补码: 1111 1111 1111 1101    //注意符号位不变

而在计算机中加法不用说,直接加。减法在真正计算中都是转化为+补码的形式计算:

5 - 3 = 5 + ( -3 ) 
0000 0000 0000 0101 + 1111 1111 1111 1101 = 1 0000 0000 0000 0010

那么首先

① 为什么都转化为加法运算呢,因为CPU只有加法器,为什么CPU不设计减法器呢,我觉得除去设计难度(即假设可以实现,有待探讨减法器的可行性),从数学/哲学上说,减一个数和加这个数的相反数其实是一样的。

 

② 在现有的补码计算规则下,减法转化为加补码的原理(正确性)如何保证)?

       可以确定的是,正确性已经包含在补码的计算规则中,应该是先有加补码的idea,再有补码的计算规则,这和C语言的变量命名规则——只能下划线,数字和字母组成并且开头不能为数字一样,应该是先设计常量的命名规则,然后再在它的余集中选取变量的命名规则是一样的,先想下蛋,才有鸡嘛:)

       现在要搞清楚的是,加补码的结果是正确的。下面证明。

1)先感性认识一下,考虑这样一个问题:有一块钟表的快了两个小时(假设现在钟表2点),怎么将其恢复正常?

        最直接的方法肯定是直接将时针往回拨2小时,但是还有一个方法:

      将时针往前拨12-2 = 10个小时。

        即对于表盘而言,  - n = + 12 - n (0< = n <= 12)。

        同样地,对于大于12的n值,可以使用取余(取模)解决这个问题:- n = + (-n)%12  (n >= 0 )(其实[0,12]是特例而已),可以看到,-2,-14,-26 ...%12 = 2,即往回拨2,14,26...小时效果和往前拨10小时都是一样的,这和实际的经验吻合。

       上面是12进制的问题,现在将问题拓展,考虑整数n∈[0,1 0000 0000 0000 0000](二进制)之间的减法问题:

 

     减n = 加上对-n求128的余

        -n = + 1 0000 0000 0000 0000 - n = + 0000 0000 0000 0001 +1111 1111 1111 1111 - n

             =+ 1 + (-n)的反码 

             = (-n)的补码

 

   -n的补码就是对-n求1 0000 0000 0000 0000 的余 !

不过,上面有两个小细节:

1)1111 1111 1111 1111 - n = (-n)的补码

      如果直接从负数的反码来考虑,好像并不是1111 1111 1111 1111 - n,而是1 0 1111 1111 1111 1111 - n,因为负数的符号位没有变。但是这里n为正数,是直接从+n原码求-n反码的,例如求-3反码的过程:+3原码:0000 0000 0000 0011—— -3原码:1000 0000 0000 0011—— -3反码:1111 1111 1111 1100,如果掐去中间过程:

         +3原码:0000 0011—— -3反码:1111 1111 1111 1100

         是不是就是1111 1111 1111 1111 - 0000 0000 0000 0011  ?

2)正数只到127的情况下,减128不会出问题?

    另外,为了简单考虑,考虑一下8位二进制,对于-128,其实并没有超出范围,回到钟表例子,正数范围是1,...,11,12,如果从0开始数,则是0 ... 11。但是求余法则一样适用于“回拨12小时”的情况,因为求余的底数用的是12...所以数为[0,127],而支持的减法可以减到128,故8位二进制可以支持的最小负数可以到-128。

 

证法二:

踏实计算,证明真正的减法过程和加补码是一样的:正确性蕴含在补码的求取规则中。

假设A,B均正,且符号位参与运算,直接运用十进制减法规则:低位直接相减,不够向高位借位,则

a. |A| >= |B|,则最高位不需要借位,符号位0-0=0,正确,即|A| >= |B|时,可以直接将符号位参与运算,不影响结果,但是为不涉及具体计算过程(真的进行数值部分减法),可以这样看:

     |A| - |B| =  |A| + 1111 1111 1111 1111 - |B| - 1111 1111 1111 1111

                   =  |A| + (-|B|)反码 - 1111 1111 1111 1111

                   =  |A| + (-|B|)反码 +1  - 1111 1111 1111 1111 - 1

                   =   |A| + (-|B|)补码 - 1 0000 0000 0000 0000

(也可以使用|A| + 1 0000 0000 0000 0000 - |B| - 1 0000 0000 0000 0000 直接推)

由于|A|,|B|为-128 ~ 127 之间的数,循环周期为 256  = 1 0000 0000 0000 0000,故

|A| - |B| 的最终结果 - 1 0000 0000 0000 0000相当于 -1 -1 -1 ... -1退回256步,回到原点。

或者从这个结论出发,|A| - |B| = |A| - |B| + 1 0000 0000 0000 0000 = |A| + (-|B|)补码

      

b. |A| < |B|, 数值部分不够用,要借位,最高位前面是符号位,向符号位借一位,但是符号位为0,只能向“虚空”借一位(+ 1 0000 0000 0000 0000),这样刚好符号位也正确了(剩下了一个1 -0 =0),数值部分也够用了,故等效+1 1000 0000 0000 0000参与运算:

       |A| - |B|  = |A|原码 + 1 0000 0000 0000 0000 - |B|原码

                      = |A|原码 + 0000 0000 0000 0001 +1111 1111 1111 1111 - |B|原码

                      = | A|原码 + 1 + (-|B|)的反码 

                      =|A|原码 +(-|B|)的补码

 

 

 

       综上,A-B = |A| + (-|B|)补码

      以后证明,不用分大小讨论,直接用|A| - |B| = |A| - |B| + 1 0000 0000 0000 0000 = |A| + (-|B|)补码,从这个角度来看,其实还是用到了  “减法——>加上周期取余” 的转化方法,将减法的过程移到求补码的过程中去。

       所以|A| - |B| = |A| - |B| + 1 0000 0000 0000 0000 = |A| + (-|B|)补码的证明方法兼具两种证法的优点——原理简明,过程严瑾。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

参考资料:

【1】https://blog.csdn.net/briblue/article/details/70296326

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值