From d0cea6f6ccffd7e6c3b63e14321d13591062b59b Mon Sep 17 00:00:00 2001 From: "18218461270@163.com" <18218461270@163.com> Date: Thu, 31 Jul 2025 13:45:15 +0800 Subject: [PATCH] update chapter2 homework --- homework/chapter2/65.c | 21 ++++++++++++++------- homework/chapter2/66.c | 26 +++++++++++++++----------- homework/chapter2/75.c | 24 ++++++++++++++++-------- homework/chapter2/80.c | 25 ++++++++++++++++--------- homework/chapter2/95.c | 14 +++++++------- homework/chapter2/97.c | 16 ++++++++-------- homework/chapter2/README.md | 4 ++-- 7 files changed, 78 insertions(+), 52 deletions(-) diff --git a/homework/chapter2/65.c b/homework/chapter2/65.c index 1e737f5..0e63aa2 100644 --- a/homework/chapter2/65.c +++ b/homework/chapter2/65.c @@ -1,16 +1,23 @@ -#include +#include +#include /* 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); + x ^= x >> 16; + x ^= x >> 8; + x ^= x >> 4; + x ^= x >> 2; + x ^= x >> 1; return x & 1; } 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; + } + } } \ No newline at end of file diff --git a/homework/chapter2/66.c b/homework/chapter2/66.c index 37518dd..94fd515 100644 --- a/homework/chapter2/66.c +++ b/homework/chapter2/66.c @@ -1,4 +1,5 @@ -#include +#include +#include /* * Generate mask indicating leftmost 1 in x. Assume w=32. @@ -7,20 +8,23 @@ */ int leftmost_one(unsigned x) { unsigned t = x; - t = t >> 1; + t >>= 1; - t = t | (t >> 1); - t = t | (t >> 2); - t = t | (t >> 4); - t = t | (t >> 8); - t = t | (t >> 16); + t |= t >> 1; + t |= t >> 2; + t |= t >> 4; + t |= t >> 8; + 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)); + for (unsigned x = 0; ; x++) { + assert((x == 0 && leftmost_one(x) == 0) || (x != 0 && leftmost_one(x) == (1 << (31 - __builtin_clz(x))))); + + if (x == UINT_MAX) { + break; + } + } } \ No newline at end of file diff --git a/homework/chapter2/75.c b/homework/chapter2/75.c index 75b68ee..ed5584b 100644 --- a/homework/chapter2/75.c +++ b/homework/chapter2/75.c @@ -1,5 +1,6 @@ #include #include +#include int signed_high_prod(int x, int 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); } +unsigned randu() { + if (rand() & 1) { + return rand(); + } else { + return ~rand(); + } +} + 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); + assert(RAND_MAX == INT_MAX); + + const int test_cases = 1e8; + for (int i = 0; i < test_cases; i++) { + unsigned x = randu(), y = randu(); + assert((unsigned long long) x * y == ((unsigned long long) unsigned_high_prod(x, y) << 32) + x * y); + } } \ No newline at end of file diff --git a/homework/chapter2/80.c b/homework/chapter2/80.c index 44b0a0a..53e67c8 100644 --- a/homework/chapter2/80.c +++ b/homework/chapter2/80.c @@ -1,19 +1,26 @@ #include +#include +#include int threefourths(int x) { 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 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(RAND_MAX == INT_MAX); + + const int test_cases = 1e8; + for (int i = 0; i < test_cases; i++) { + int x = randi(); assert(threefourths(x) == (long long) x * 3 / 4); } } \ No newline at end of file diff --git a/homework/chapter2/95.c b/homework/chapter2/95.c index 984fc97..2cf56e1 100644 --- a/homework/chapter2/95.c +++ b/homework/chapter2/95.c @@ -7,31 +7,31 @@ typedef unsigned float_bits; /* computs 0.5*f. If f is NaN, then return f. */ 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; } if (e > 1) { - e = e - 1; + e--; return s | (e << 23) | f; } if (e == 1) { - f = f | (1 << 23); + f |= 1 << 23; e = 0; } int t = f; - f = f >> 1; + f >>= 1; if (t & f & 1) { - f = f + 1; + f++; } return s | (e << 23) | f; } int main() { - for (float_bits x = 0; ; x = x + 1) { + for (float_bits x = 0; ; x++) { float *a = (float*) &x; float b = 0.5 * *a; float_bits c = float_half(x); diff --git a/homework/chapter2/97.c b/homework/chapter2/97.c index b18165a..4b3410b 100644 --- a/homework/chapter2/97.c +++ b/homework/chapter2/97.c @@ -7,7 +7,7 @@ typedef unsigned float_bits; /* Compute (float) i */ float_bits float_i2f(int i) { if (i == INT_MIN) { - return 0xCF000000U; + return 0xCF000000; } if (i == 0) { @@ -17,23 +17,23 @@ float_bits float_i2f(int i) { float_bits s = 0, f, e; if (i < 0) { i = -i; - s = 0x80000000U; + s = 0x80000000; } int hb = 30; while (!(i >> hb)) { - hb = hb - 1; + hb--; } - i = i ^ (1 << hb); + i ^= 1 << hb; e = hb + 127; if (hb > 23) { f = i >> (hb - 23); if ((i & (1 << (hb - 24))) && ((f & 1) || (i & ((1 << (hb - 24)) - 1)))) { - f = f + 1; - if (f & 0x00800000U) { + f++; + if (f & 0x00800000) { f = 0; - e = e + 1; + e++; } } } else { @@ -44,7 +44,7 @@ float_bits float_i2f(int i) { } int main() { - for (int x = INT_MIN; ; x = x + 1) { + for (int x = INT_MIN; ; x++) { float_bits y = float_i2f(x); float *z = (float*) &y; assert(*z == (float) x); diff --git a/homework/chapter2/README.md b/homework/chapter2/README.md index 06ef80a..0142980 100644 --- a/homework/chapter2/README.md +++ b/homework/chapter2/README.md @@ -1,5 +1,5 @@ ## 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$ 的符号(决定舍入方向)进行修正。 ## 2.97 -注意在某些情况下,舍入会导致有效位数增加。 \ No newline at end of file +在某些情况下,舍入会导致最高位变化。对于这种情况,我们要将最低有效位提高一位。 \ No newline at end of file