update chapter2 homework

This commit is contained in:
18218461270@163.com 2025-07-31 13:45:15 +08:00
parent 119b77eefb
commit d0cea6f6cc
7 changed files with 78 additions and 52 deletions

View File

@ -1,16 +1,23 @@
#include <stdio.h> #include <assert.h>
#include <limits.h>
/* Return 1 when x contains an odd number of 1s; 0 otherwise. /* Return 1 when x contains an odd number of 1s; 0 otherwise.
Assume w=32 */ Assume w=32 */
int odd_ones(unsigned x) { int odd_ones(unsigned x) {
x = x ^ (x >> 16); x ^= x >> 16;
x = x ^ (x >> 8); x ^= x >> 8;
x = x ^ (x >> 4); x ^= x >> 4;
x = x ^ (x >> 2); x ^= x >> 2;
x = x ^ (x >> 1); x ^= x >> 1;
return x & 1; return x & 1;
} }
int main() { int main() {
printf("%d %d\n", odd_ones(0xF1F1F0F1), odd_ones(0xFF00AAAA)); for (unsigned x = 0; ; x++) {
assert(odd_ones(x) == __builtin_parity(x));
if (x == UINT_MAX) {
break;
}
}
} }

View File

@ -1,4 +1,5 @@
#include <stdio.h> #include <assert.h>
#include <limits.h>
/* /*
* Generate mask indicating leftmost 1 in x. Assume w=32. * Generate mask indicating leftmost 1 in x. Assume w=32.
@ -7,20 +8,23 @@
*/ */
int leftmost_one(unsigned x) { int leftmost_one(unsigned x) {
unsigned t = x; unsigned t = x;
t = t >> 1; t >>= 1;
t = t | (t >> 1); t |= t >> 1;
t = t | (t >> 2); t |= t >> 2;
t = t | (t >> 4); t |= t >> 4;
t = t | (t >> 8); t |= t >> 8;
t = t | (t >> 16); t |= t >> 16;
return (t + 1) & x; return (t + 1) & x;
} }
int main() { int main() {
printf("%.8X %.8X\n", 0x06050403, leftmost_one(0x06050403)); for (unsigned x = 0; ; x++) {
printf("%.8X %.8X\n", 0xF0F0F0F0, leftmost_one(0xF0F0F0F0)); assert((x == 0 && leftmost_one(x) == 0) || (x != 0 && leftmost_one(x) == (1 << (31 - __builtin_clz(x)))));
printf("%.8X %.8X\n", 0x00000000, leftmost_one(0x00000000));
printf("%.8X %.8X\n", 0x00000001, leftmost_one(0x00000001)); if (x == UINT_MAX) {
break;
}
}
} }

View File

@ -1,5 +1,6 @@
#include <limits.h> #include <limits.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h>
int signed_high_prod(int x, int y) { int signed_high_prod(int x, int y) {
long long p = (long long) x * y; long long p = (long long) x * y;
@ -11,13 +12,20 @@ unsigned unsigned_high_prod(unsigned x, unsigned y) {
return signed_high_prod(x, y) + (((int) y >> (w - 1)) & x) + (((int) x >> (w - 1)) & y); return signed_high_prod(x, y) + (((int) y >> (w - 1)) & x) + (((int) x >> (w - 1)) & y);
} }
unsigned randu() {
if (rand() & 1) {
return rand();
} else {
return ~rand();
}
}
int main() { int main() {
unsigned x = 0x71827364, y = 0xF0E1D2C3; assert(RAND_MAX == INT_MAX);
assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y);
x = 0x91827364, y = 0xF0E1D2C3; const int test_cases = 1e8;
assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y); for (int i = 0; i < test_cases; i++) {
x = 0x71827364, y = 0x60E1D2C3; unsigned x = randu(), y = randu();
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); assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y);
} }
}

View File

@ -1,19 +1,26 @@
#include <assert.h> #include <assert.h>
#include <limits.h>
#include <stdlib.h>
int threefourths(int x) { int threefourths(int x) {
int p = x >> 2, q = x & 3; int p = x >> 2, q = x & 3;
return p + (p << 1) + q + ((!q | (x >> 31)) & 1) - 1; return p + (p << 1) + q - ((!!q & (~x >> 31)) & 1);
}
int randi() {
if (rand() & 1) {
return rand();
} else {
return ~rand();
}
} }
int main() { int main() {
int x = 0x88659612; assert(RAND_MAX == INT_MAX);
for (int i = 0; i < 100; i++) {
x++; const int test_cases = 1e8;
assert(threefourths(x) == (long long) x * 3 / 4); for (int i = 0; i < test_cases; i++) {
} int x = randi();
x = 0x79642695;
for (int i = 0; i < 100; i++) {
x++;
assert(threefourths(x) == (long long) x * 3 / 4); assert(threefourths(x) == (long long) x * 3 / 4);
} }
} }

View File

@ -7,31 +7,31 @@ typedef unsigned float_bits;
/* computs 0.5*f. If f is NaN, then return f. */ /* computs 0.5*f. If f is NaN, then return f. */
float_bits float_half(float_bits uf) { float_bits float_half(float_bits uf) {
float_bits s = uf & 0x80000000U, f = uf & 0x007FFFFF, e = (uf >> 23) & 0xFF; float_bits s = uf & 0x80000000, f = uf & 0x007FFFFF, e = (uf >> 23) & 0xFF;
if (e == 0xFFU) { if (e == 0xFF) {
return uf; return uf;
} }
if (e > 1) { if (e > 1) {
e = e - 1; e--;
return s | (e << 23) | f; return s | (e << 23) | f;
} }
if (e == 1) { if (e == 1) {
f = f | (1 << 23); f |= 1 << 23;
e = 0; e = 0;
} }
int t = f; int t = f;
f = f >> 1; f >>= 1;
if (t & f & 1) { if (t & f & 1) {
f = f + 1; f++;
} }
return s | (e << 23) | f; return s | (e << 23) | f;
} }
int main() { int main() {
for (float_bits x = 0; ; x = x + 1) { for (float_bits x = 0; ; x++) {
float *a = (float*) &x; float *a = (float*) &x;
float b = 0.5 * *a; float b = 0.5 * *a;
float_bits c = float_half(x); float_bits c = float_half(x);

View File

@ -7,7 +7,7 @@ typedef unsigned float_bits;
/* Compute (float) i */ /* Compute (float) i */
float_bits float_i2f(int i) { float_bits float_i2f(int i) {
if (i == INT_MIN) { if (i == INT_MIN) {
return 0xCF000000U; return 0xCF000000;
} }
if (i == 0) { if (i == 0) {
@ -17,23 +17,23 @@ float_bits float_i2f(int i) {
float_bits s = 0, f, e; float_bits s = 0, f, e;
if (i < 0) { if (i < 0) {
i = -i; i = -i;
s = 0x80000000U; s = 0x80000000;
} }
int hb = 30; int hb = 30;
while (!(i >> hb)) { while (!(i >> hb)) {
hb = hb - 1; hb--;
} }
i = i ^ (1 << hb); i ^= 1 << hb;
e = hb + 127; e = hb + 127;
if (hb > 23) { if (hb > 23) {
f = i >> (hb - 23); f = i >> (hb - 23);
if ((i & (1 << (hb - 24))) && ((f & 1) || (i & ((1 << (hb - 24)) - 1)))) { if ((i & (1 << (hb - 24))) && ((f & 1) || (i & ((1 << (hb - 24)) - 1)))) {
f = f + 1; f++;
if (f & 0x00800000U) { if (f & 0x00800000) {
f = 0; f = 0;
e = e + 1; e++;
} }
} }
} else { } else {
@ -44,7 +44,7 @@ float_bits float_i2f(int i) {
} }
int main() { int main() {
for (int x = INT_MIN; ; x = x + 1) { for (int x = INT_MIN; ; x++) {
float_bits y = float_i2f(x); float_bits y = float_i2f(x);
float *z = (float*) &y; float *z = (float*) &y;
assert(*z == (float) x); assert(*z == (float) x);

View File

@ -1,5 +1,5 @@
## 2.65 ## 2.65
一次操作将 $w$ 位的整数 $x$ 从中间分成两个 $\frac{w}{2}$ 位的整数 $y$ 和 $z$,接着令 `x = y ^ z`。进行该操作 5 次后得到答案。 一次操作将 $w$ 位的整数 $x$ 从中间分成两个 $\frac{w}{2}$ 位的整数 $y$ 和 $z$,接着令 `x = y ^ z`。进行 5 次操作得到答案。
我们将这样的思路称为“折半递归法”。 我们将这样的思路称为“折半递归法”。
@ -31,4 +31,4 @@ b&=(a+x_{w-1}\cdot y+y_{w-1}\cdot x)\bmod 2^w\\
先得到粗糙的结果 `(x >> 2) + ((x >> 2) << 1)`,再根据 `x & 3` 以及 $x$ 的符号(决定舍入方向)进行修正。 先得到粗糙的结果 `(x >> 2) + ((x >> 2) << 1)`,再根据 `x & 3` 以及 $x$ 的符号(决定舍入方向)进行修正。
## 2.97 ## 2.97
注意在某些情况下,舍入会导致有效位数增加 在某些情况下,舍入会导致最高位变化。对于这种情况,我们要将最低有效位提高一位