继续更新习题。

参考资料:

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;
}

总结

第二章的习题总算是整理完了,也算是收获满满,不过测试部分还是有很多冗余,后续整理的时候应该会单独写一个测试类,这样就会减少很多代码量。