深入理解计算机系统 第2章 习题解析 Part5
继续更新习题。
参考资料:
https://dreamanddead.gitbooks.io/csapp-3e-solutions/content/
Chapter 2
86
描述 | 值 | 十进制 |
---|---|---|
最小的正非规格化数 | 0 0…0 0 0…01 | $2^{-n+2-2^{k-1}}$ |
最小的正规格化数 | 0 0…01 1 0…0 | $2^{2-2^{k-1}}$ |
最大的规格化数 | 0 1…10 1 1…1 | $(2-2^{-n})\times 2^{2^{k-1} -1}$ |
计算过程:
最小的正非规格化数:
值:
0 0...0 0 0...01
十进制:
最小的正规格化数:
值:
0 0...01 1 0...0
十进制:
最大的规格化数:
值:
0 1...10 1 1...1
十进制:
87
88
A | B | ||
---|---|---|---|
位 | 值 | 位 | 值 |
$1\ 01110\ 001$ | $\frac{-9}{16}$ | $1\ 0110\ 0010$ | $\frac{-9}{16}$ |
$0\ 10110\ 101$ | $208$ | $0\ 1110\ 1010$ | $208$ |
$1\ 00111\ 110$ | $-\frac{7}{2^{10}}$ | $1\ 0000\ 0111$ | $-\frac{7}{2^{10}}$ |
$0\ 00000\ 101$ | $\frac{5}{2^{17}}$ | $0\ 0000\ 0001$ | $\frac{1}{2^{10}}$ |
$1\ 11011\ 000$ | $-2^{12}$ | $1\ 1110\ 1111$ | $-248$ |
$0\ 11000\ 100$ | $768$ | $0\ 1111\ 0000$ | $+\infty$ |
89
A.
正确,因为float的表示范围超过int。
B.
不正确,取
x = INT_MIN;
y = INT_MAX;
C.
正确,因为int转换为double后相加的范围不会超过double。
D.
相乘可能产生舍入,具体的例子为
x = 0x64e73387;
y = 0xd31cb264;
z = 0xd22f1fcd;
参考资料:
https://dreamanddead.gitbooks.io/csapp-3e-solutions/content/chapter2/2.89.html
大佬说利用brute force attack可以得到上述结果,不过直接穷举好像运算时间太长,目前还没找到比较快速得出结果的方法。
E.
不正确,取
x = 1;
z = 0;
代码:
#include <stdio.h>
#include <limits.h>
#include <time.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, size_t len) {
size_t i;
for (i = 0; i < len; i++){
printf("%.2x", start[i]);
}
printf("\n");
}
int B(int x, int y){
double dx = (double) x;
double dy = (double) y;
if (dx - dy != (double)(x - y)){
return 0;
}else{
return 1;
}
}
int D(int x, int y, int z){
double dx = (double) x;
double dy = (double) y;
double dz = (double) z;
if (((dx * dy) * dz) != (dx * (dy * dz))){
return 0;
}else{
return 1;
}
}
int E(int x, int z){
double dx = (double) x;
double dz = (double) z;
if ((dx / dx) != (dz / dz)){
return 0;
}else{
return 1;
}
}
int main(){
int b = B(INT_MIN, INT_MAX);
printf("B: %d\n", b);
int e = E(1, 0);
printf("E: %d\n", e);
return 0;
}
90
能表示的最小数为
最小的规格化数为
小于此数时即为非规格化的数。
最大的规格化数(形式为$2^x$)为
大于此数即为正无穷。
代码如下:
#include <stdio.h>
#include <math.h>
const float EPS = 1e-10;
float u2f(unsigned x){
return *(float *)&x;
}
float fpwr2(int x){
/* Result exponent and fraction*/
unsigned exp, frac;
unsigned u;
if(x < -149) {
/* Too small. Return 0.0 */
exp = 0;
frac = 0;
} else if (x < -126) {
/* Denormalized result*/
exp = 0;
frac = 1 << (22 + x + 127);
} else if (x < 128) {
/*Normalized result.*/
exp = x + 127;
frac = 1;
} else {
/*Too big. Return +oo*/
exp = 255;
frac = 0;
}
/* Pack exp and frac into 32 bits */
u = exp << 23 | frac;
/*Return as float */
return u2f (u);
}
void test(){
int x[6] = {-127, -100, 0, 100, 150};
for (int i = 1; i < 5; i++){
if (abs(fpwr2(x[i]) - powf(2, x[i])) >= EPS){
printf("Wrong answer for %d!\n", x[i]);
return;
}
}
printf("Pass test!\n");
return;
}
int main(){
test();
return 0;
}
总结
第二章的习题总算是整理完了,也算是收获满满,不过测试部分还是有很多冗余,后续整理的时候应该会单独写一个测试类,这样就会减少很多代码量。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Doraemonzzz!
评论
ValineLivere