2.37
原代码用malloc
申请了指 定 类 型 的 大 小 个 数 字节的空间,如果成功分配了空间,就对这段空间进行赋值。
需要注意的是,malloc
定义中,参数类型是int
,所以A.
中即使把asize
改成了64位数据类型,依然不能赋值足够的空间。换句话说,只要用同一个分配空间的函数,我们就永远无法赋值超过 字节的空间。我们只能让函数在遇到分配超过 字节的时候返回一个表示“执行失败”的空指针。
需要注意的是,在C/C++语言的库中,表示数量一类的变量用的都是无符号类型。那么下面的代码就会出现一些问题:
1 2 3 4 5 6 7 vector<int >num; int sum = 0 ;for (int i = 0 ;i <= num.size () - 1 ;i++) { sum += num[i]; }
应该如何修改这段代码?
2.71
原代码最后只保留了8个字节,没有符号扩展为32位。
1 2 int bits = bytenum << 3 ;return word >> bits << 24 >> (24 - bits);
2.75
如果x和y都是正数,显然他们有没有符号都没区别了。我们主要讨论负数的情况。 考虑signed_high_prod
是如何实现的。最终的返回值其实是 的高 位,那么计算时signed_high_prod
需要先符号扩展为 位,也就是在前面补了 个1(二进制意义下)。 我们以16位扩展到32位举例。设原来是32位的0x 和0x ,在signed_high_prod
函数中符号扩展后变成了0xFFFF 和0xFFFF 。但是我们要计算的是无符号数,也就是说它不应该被扩展,我们希望的是在前面填0而非1。 下一步,如果我们能让两个乘数的高16位被加上1,他们就相当于变成了没有被扩展过的无符号数了。也就是说我们要给这两个数相乘的结果先加上0xFFFF ,根据乘法分配律,原式变成了0x0000$p_0p_1p_2p_3 q_0q_1q_2q_3, 那 么 再 加 上 p_0p_1p_2p_3(1<<16), 再 用 乘 法 分 配 律 , 就 变 成 了 我 们 希 望 的 p_0p_1p_2p_3和 q_0q_1q_2q_3。 我 们 回 顾 我 们 加 上 的 两 个 乘 数 , 化 简 之 后 其 实 就 是 p_0p_1p_2p_3和 q_0q_1q_2q_3$0000。我们要写unsigned_high_prod
,其实就是把signed_high_prod
的结果加上这两个数抹去后16位的结果。
参考代码:
1 2 3 4 5 6 unsigned unsigned_high_prod (unsigned x, unsigned y) { signed sig_x = x >> (w - 1 ); signed sig_y = y >> (w - 1 ); signed signed_prod = signed_high_prod (x, y); return signed_prod + x * sig_y + y * sig_x; }
2.77
不难发现位运算和乘法运算是有一定关系的。十进制下乘以 就相当于原数末尾追加一个 ,同样地,二进制下左移一位相当于乘以 。
换句话讲,我们可以把乘数的二进制表示展开,于是有 这里的 要么是0,要么是1,于是以上的公式通过一系列变换后可以用以下的公式表示:
1 2 3 4 5 6 7 8 9 int mul (int x,int y) { int ans=0 ; for (int i = 0 ;i <= 31 ;++i){ if (y & (1 << i)){ ans += x << i; } } return ans; }
实际的CPU中是有专门的电路来计算乘法的(乘法消耗的时间依然是加法的数倍),因此我们一般不需要这样写。但是,整数的乘方也是我们常见的运算之一,CPU却没有这样的电路。你能根据上面的推导,举一反三,写出如何高效计算一个数的幂(指数为自然数)的方法吗?
参考代码:计算
1 2 3 4 5 6 7 8 int mul (int a,int b,int p) { int ans = 1 ; for (; b; b >>= 1 ){ if (b & 1 ) ans = ans * a % p; a = a * a % p; } return ans; }
注意如果p比较大,中间过程可能溢出,需要使用long long
。不同于暴力求解,在b
是32位时,这串代码中的for
最多循环32次,非常高效。甚至,如果 和 都是矩阵,上述推理依然成立。你可以再次推导一遍,但是在学习“代数结构”这一板块的数学知识后(将在大二下学习),你可能对这些知识的理解会更加深刻。
2.83
我们把每 位看做一个整体,前 位中,每一位在十进制下的值依次为
那么接下来 位代表的值就是上式求和再乘 ,以此类推,记上式的值为 ,所以整个串的数值就是
2.86
类比32位浮点数阶码(8位)的-126~127,80位浮点数阶码(15位)是-16382~16383。