Compare commits
2 Commits
69ccb5bb4f
...
0ce09fc1c5
Author | SHA1 | Date | |
---|---|---|---|
0ce09fc1c5 | |||
9f3ddf28d7 |
16
homework/chapter2/65.c
Normal file
16
homework/chapter2/65.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* Return 1 when x contains an odd number of 1s; 0 otherwise.
|
||||||
|
Assume w=32 */
|
||||||
|
int odd_ones(unsigned x) {
|
||||||
|
x = x ^ (x >> 16);
|
||||||
|
x = x ^ (x >> 8);
|
||||||
|
x = x ^ (x >> 4);
|
||||||
|
x = x ^ (x >> 2);
|
||||||
|
x = x ^ (x >> 1);
|
||||||
|
return x & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("%d %d\n", odd_ones(0xF1F1F0F1), odd_ones(0xFF00AAAA));
|
||||||
|
}
|
26
homework/chapter2/66.c
Normal file
26
homework/chapter2/66.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate mask indicating leftmost 1 in x. Assume w=32.
|
||||||
|
* For example, 0xFF00 -> 0x8000, and 0x6600 --> 0x4000.
|
||||||
|
* If x = 0, then return 0.
|
||||||
|
*/
|
||||||
|
int leftmost_one(unsigned x) {
|
||||||
|
unsigned t = x;
|
||||||
|
t = t >> 1;
|
||||||
|
|
||||||
|
t = t | (t >> 1);
|
||||||
|
t = t | (t >> 2);
|
||||||
|
t = t | (t >> 4);
|
||||||
|
t = t | (t >> 8);
|
||||||
|
t = t | (t >> 16);
|
||||||
|
|
||||||
|
return (t + 1) & x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("%.8X %.8X\n", 0x06050403, leftmost_one(0x06050403));
|
||||||
|
printf("%.8X %.8X\n", 0xF0F0F0F0, leftmost_one(0xF0F0F0F0));
|
||||||
|
printf("%.8X %.8X\n", 0x00000000, leftmost_one(0x00000000));
|
||||||
|
printf("%.8X %.8X\n", 0x00000001, leftmost_one(0x00000001));
|
||||||
|
}
|
23
homework/chapter2/75.c
Normal file
23
homework/chapter2/75.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include <limits.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
int signed_high_prod(int x, int y) {
|
||||||
|
long long p = (long long) x * y;
|
||||||
|
return p >> 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned unsigned_high_prod(unsigned x, unsigned y) {
|
||||||
|
int w = sizeof(int) << 3;
|
||||||
|
return signed_high_prod(x, y) + (((int) y >> (w - 1)) & x) + (((int) x >> (w - 1)) & y);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
unsigned x = 0x71827364, y = 0xF0E1D2C3;
|
||||||
|
assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y);
|
||||||
|
x = 0x91827364, y = 0xF0E1D2C3;
|
||||||
|
assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y);
|
||||||
|
x = 0x71827364, y = 0x60E1D2C3;
|
||||||
|
assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y);
|
||||||
|
x = 0x91827364, y = 0x60E1D2C3;
|
||||||
|
assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y);
|
||||||
|
}
|
20
homework/chapter2/80.c
Normal file
20
homework/chapter2/80.c
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int threefourths(int x) {
|
||||||
|
int p = x >> 2, q = x & 3;
|
||||||
|
return p + (p << 1) + q + ((!q | (x >> 31)) & 1) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int x = 0x88659612;
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
x++;
|
||||||
|
assert(threefourths(x) == (long long) x * 3 / 4);
|
||||||
|
}
|
||||||
|
x = 0x79642695;
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
x++;
|
||||||
|
assert(threefourths(x) == (long long) x * 3 / 4);
|
||||||
|
}
|
||||||
|
}
|
21
homework/chapter2/README.md
Normal file
21
homework/chapter2/README.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
## 2.65
|
||||||
|
定义一次操作为将 $w$ 位的整数 $x$ 从中间分成两个 $\frac{w}{2}$ 位的整数 $y$ 和 $z$,接着令 `x=y^z`。进行该操作 5 次后得到答案。
|
||||||
|
|
||||||
|
我们将这样的思路称为“折半递归法”。
|
||||||
|
## 2.66
|
||||||
|
第一次操作,我们令 `x = x | (x >> 1)`,这样 $x$ 的最高位所在 `1` 连续段长度必然不小于 2。
|
||||||
|
|
||||||
|
第二次操作,令 `x = x | (x >> 2)`,依次类推。通过 5 次操作即可实现提示中的转换。
|
||||||
|
## 2.75
|
||||||
|
$x,y$ 是无符号整数,$x'=U2T_w(x),y'=U2T_w(y)$。
|
||||||
|
|
||||||
|
$$
|
||||||
|
\begin{aligned}
|
||||||
|
x'\times y'&=(x+x_{w-1}2^w)\times(y+y_{w-1}2^w)\\
|
||||||
|
&=x\times y+(x_{w-1}\times y+y_{w-1}\times x)2^w+x_{w-1}y_{w-1}2^{2w}
|
||||||
|
\end{aligned}$$
|
||||||
|
|
||||||
|
因此有 $U2B_{2w}(x'\times y')=T2B_{2w}(x\times y+(x_{w-1}\times y+y_{w-1}\times x)2^w)$。即令 `a = signed_high_prod(x, y), b = unsigned_high_prod(x', y')`,$T2B_w(a+x_{w-1}\times y+y_{w-1}\times x)=U2B_w(b)$。
|
||||||
|
|
||||||
|
## 2.80
|
||||||
|
先得到粗糙的答案 `(x >> 2) + ((x >> 2) << 1)`,再根据 `x & 3` 进行修正。
|
@ -4,7 +4,7 @@
|
|||||||
## `isTmax`
|
## `isTmax`
|
||||||
$Tmax$ 的位表示为 `011...11`。注意到 `x+1==~x` 当且仅当 $x=-1$ 或 $x=Tmax$。利用该性质,并判断是否为 $-1$。
|
$Tmax$ 的位表示为 `011...11`。注意到 `x+1==~x` 当且仅当 $x=-1$ 或 $x=Tmax$。利用该性质,并判断是否为 $-1$。
|
||||||
## `allOddBits`
|
## `allOddBits`
|
||||||
每次将 $w$ 位的整数 $x$ 分成 $\frac{w}{2}$ 位的两段,将两者按位与得到新的 $x$,进行该操作 4 次后 $x$ 位数为 2,检验第 1 位(从 0 开始编号)是否为 `1` 。
|
使用“折半递归法”,参见作业 2.65。
|
||||||
## `negate`, `isAsciiDigit`
|
## `negate`, `isAsciiDigit`
|
||||||
略。
|
略。
|
||||||
## `conditional`
|
## `conditional`
|
||||||
@ -14,10 +14,10 @@ $Tmax$ 的位表示为 `011...11`。注意到 `x+1==~x` 当且仅当 $x=-1$ 或
|
|||||||
## `isLessOrEqual`
|
## `isLessOrEqual`
|
||||||
核心思路是判断 `y - x = y + ~x + 1` 的符号位。需要处理一些细节以规避溢出带来的错误。
|
核心思路是判断 `y - x = y + ~x + 1` 的符号位。需要处理一些细节以规避溢出带来的错误。
|
||||||
## `logicalNeg`
|
## `logicalNeg`
|
||||||
采用 `allOddBits` 方法,略。
|
“折半递归法”。
|
||||||
## `howManyBits`
|
## `howManyBits`
|
||||||
对于正数 $x$,所求为最大的 $b$ 使得 $x$ 的第 $b-2$ 位为 `1`,而对于负数 $x$,则是最大的 $b$ 使得 $x$ 的第 $b-2$ 位为 `0`。通过令 `x = x ^ ((x >> 31) << 31)`,我们得以仅用考虑 $x$ 为正数的情况。
|
对于正数 $x$,所求为最大的 $b$ 使得 $x$ 的第 $b-2$ 位为 `1`,而对于负数 $x$,则是最大的 $b$ 使得 $x$ 的第 $b-2$ 位为 `0`。通过令 `x = x ^ ((x >> 31) << 31)`,我们得以仅用考虑 $x$ 为正数的情况。
|
||||||
|
|
||||||
之后亦可采用 `allOddBits` 方法,略。
|
之后使用“折半递归法”。
|
||||||
## `floatScale2`,`floatFloat2Int`,`floatPower2`
|
## `floatScale2`,`floatFloat2Int`,`floatPower2`
|
||||||
仔细分类即可。
|
仔细分类即可。
|
Loading…
x
Reference in New Issue
Block a user