From d30d50bad6d008ddeab7cc97d89773c07ac6b0ed Mon Sep 17 00:00:00 2001 From: "18218461270@163.com" <18218461270@163.com> Date: Wed, 23 Jul 2025 20:30:58 +0800 Subject: [PATCH] update chapter2 homework --- homework/chapter2/95.c | 45 +++++++++++++++++++++++ homework/chapter2/97.c | 73 +++++++++++++++++++++++++++++++++++++ homework/chapter2/README.md | 25 ++++++++++--- 3 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 homework/chapter2/95.c create mode 100644 homework/chapter2/97.c diff --git a/homework/chapter2/95.c b/homework/chapter2/95.c new file mode 100644 index 0000000..984fc97 --- /dev/null +++ b/homework/chapter2/95.c @@ -0,0 +1,45 @@ +#include +#include +#include + +/* Access bit-level representation of floating-point number */ +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; + + if (e == 0xFFU) { + return uf; + } + + if (e > 1) { + e = e - 1; + return s | (e << 23) | f; + } + + if (e == 1) { + f = f | (1 << 23); + e = 0; + } + int t = f; + f = f >> 1; + if (t & f & 1) { + f = f + 1; + } + return s | (e << 23) | f; +} + +int main() { + for (float_bits x = 0; ; x = x + 1) { + float *a = (float*) &x; + float b = 0.5 * *a; + float_bits c = float_half(x); + float *d = (float*) &c; + assert(b == *d || (isnan(b) && isnan(*d))); + + if (x == UINT_MAX) { + break; + } + } +} \ No newline at end of file diff --git a/homework/chapter2/97.c b/homework/chapter2/97.c new file mode 100644 index 0000000..0a22752 --- /dev/null +++ b/homework/chapter2/97.c @@ -0,0 +1,73 @@ +#include +#include + +/* Access bit-level representation of floating-point number */ +typedef unsigned float_bits; + +/* Compute (float) i */ +float_bits float_i2f(int i) { + if (i == INT_MIN) { + return 0xCF000000U; + } + + if (i == 0) { + return 0; + } + + float_bits s = 0, f, e; + if (i < 0) { + i = -i; + s = 0x80000000U; + } + + int hb = 0, t = i; + if (t >> 16) { + t = t >> 16; + hb = hb + 16; + } + if (t >> 8) { + t = t >> 8; + hb = hb + 8; + } + if (t >> 4) { + t = t >> 4; + hb = hb + 4; + } + if (t >> 2) { + t = t >> 2; + hb = hb + 2; + } + if (t >> 1) { + t = t >> 1; + hb = hb + 1; + } + + i = 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 = 0; + e = e + 1; + } + } + } else { + f = i << (23 - hb); + } + + return s | (e << 23) | f; +} + +int main() { + for (int x = INT_MIN; ; x = x + 1) { + float_bits y = float_i2f(x); + float *z = (float*) &y; + assert(*z == (float) x); + + if (x == INT_MAX) { + break; + } + } +} \ No newline at end of file diff --git a/homework/chapter2/README.md b/homework/chapter2/README.md index d16939b..c4d5494 100644 --- a/homework/chapter2/README.md +++ b/homework/chapter2/README.md @@ -7,15 +7,30 @@ 第二次操作,令 `x = x | (x >> 2)`,依次类推。通过 5 次操作即可实现提示中的转换。 ## 2.75 -$x,y$ 是无符号整数,$x'=U2T_w(x),y'=U2T_w(y)$。 +$x,y$ 是补码数,$x'=T2U_w(x),y'=T2U_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} +x'\cdot y'&=(x+x_{w-1}\cdot 2^w)\times(y+y_{w-1}\cdot 2^w)\\ +&=x\cdot y+(x_{w-1}\cdot y+y_{w-1}\cdot x)2^w+x_{w-1}\cdot y_{w-1}\cdot 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)$。 +进一步,令 `a = signed_high_prod(x, y), b = unsigned_high_prod(x', y')`,有 +$$b\cdot 2^w+x'*^u_w y'=a\cdot 2^w+T2U_w(x*^t_wy)+(x_{w-1}\cdot y+y_{w-1}\cdot x)2^w+x_{w-1}\cdot y_{w-1}\cdot 2^{2w}$$ + +化简得 +$$b=a+x_{w-1}\cdot y+y_{w-1}\cdot x+x_{w-1}\cdot y_{w-1}\cdot 2^w$$ + +即 +$$\begin{aligned} +b&=(a+x_{w-1}\cdot y+y_{w-1}\cdot x)\bmod 2^w\\ +&=T2U_w(a)+^u_t x_{w-1}\cdot y'+^u_t y_{w-1}\cdot x' +\end{aligned}$$ ## 2.80 -先得到粗糙的答案 `(x >> 2) + ((x >> 2) << 1)`,再根据 `x & 3` 进行修正。 \ No newline at end of file +先得到粗糙的结果 `(x >> 2) + ((x >> 2) << 1)`,再根据 `x & 3` 以及 $x$ 的符号(决定舍入方向)进行修正。 + +## 2.97 +注意以下细节: +- 使用“折半递归法”求 $i$ 的有效位数可以避免对于所有 $2^{32}$ 个 `int` 检验花费极长的时间; +- 在某些情况下,舍入会导致有效位数增加。 \ No newline at end of file