2_77 开始

---恢复内容开始---

前面的空缺是我忘了保存

2.77

使用位移运算和+- 实现乘法运算
A k=17 C=x<<4+x
B k=-7 C=x-(x<<3)
C k=60 C=x<<6-x<<2
D k=-112 就不做了

2.78

写出具有如下原型的函数

int divide_power2(int x,int k){
    int w=sizeof(int)*8;
    int mask=x>>w-1;
    int bios=(1<<k)-1;
//  printf("%d",bios);
    return(x+bios&mask)>>k;
}

使用负数掩码添加bios的技巧

2.79

计算函数

int mul3div4(int x){
    x=x<<1+x;
    return divide_power2(x,2);
}

//这个版本只需要先乘然后除就可以了

2.80

新的版本不要求溢出

int threefourths(int x){
    int b1=divide_power2(x,1);
    int b2=divide_power2(x,2);
    return b1+b2;
}
//这个版本可以改进的,所有的掩码应该是一样的,我就不写了

2.81

A. 1[w-n]0[n]: ~((1<<n) - 1)
B. 0[w-n-m]1[n]0[m]: ((1<<n) - 1) << m

2.82

A x<y == -x>-y
对于大部分正负合理的数是对的 ,但是极端数当 x等于 INT_MIN时不对
B (((x+y)<<4)+y-x)==17y+15x 只是加减构成了阿贝尔群 , 这样的等是没有问题
C ~x+~y+1= ~(x+y) 这个因该是对的 有这个式子 -x=~x+1 恒成立
D 对的 (ux-uy)==-(unsigned)(y-x)
E ((x>>2)<<2)<=x 因该是对的 最后的两位被归零了 其余的位不变

2.83

A. 令x为无穷序列表示的值,可以得到x*2^k = Y + x。 所以 x = Y/(2^k - 1)。 B. (a)1/7, (b)9/15 = 3/5, (c)7/63 = 1/9
表示无穷的方法

2.84

通过符号位来判断float的大小这种方法是有非常好的性质,因为浮点数的自然顺序就是如此
还是漏掉了一种方法。
有四种不同的情况
一正一负
都是零
同正
同负
((ux<<1)==0 && (uy<<1)==0) || (!sx && sy) || (!sx && !sy && ux >= uy) || (sx && sy && ux <= uy);

2.85

有k位指数 n位小数
写出阶码E,尾数M,小数f,和值V得公式

数7.0

E =10011 (共k位)
f =11000共n位
尾数
###够被准确描述的最大奇整数###
小数f 1111(全一 共N位 )
阶码 10011 (值是n) 2^(n-1) 这么大
值因该是
11111111 有n+1个 1
这个值是 2^n -1

最小的规格化数的倒数

最小的规格化数
阶码
00000001 -2^(k-1) +2// 1-bios bios=2^(k-1)-1
小数
0000000 全零代表 1
值 2^{-2^(k-1)+2}

取导之后是
2^{ 2^(k-1) -2}
阶码是 11101 只有第1位是0 // 值应该是 2^k-1 -2 + bios
2^(k-1)
尾数是全零表示1

阶数的符号表示不是补码表示,进行计算的时候要带上bios
2^k-1 -1 这个是bios 换句话讲阶数等于0是这样的 01111111 大于零的阶数首位必定是1

2.86

精度扩展的问题
80位字节下浮点数的一些特值
1 个符号位
15个阶码位
1个整数位 规格化数位1 非规格化数值为零
63个小数位
最小的 正非规格化数

2^( -2^(14) +###2### ) * 2^(-63)
//非规格化数阶数为1- bios 为了平滑的过渡
3.64510^(-4951)
最小的正规格化数
2^(-2^14 +2 )
最大的规格化数
(2-2^(-63))
2^{2 ^(14))}

2.87

在 一个符号位 五个阶码位 10个尾数位 时填表

描述HexMEVD
-0800000-0*
最小的大于2的值40010000000001100002 +2^-9*
5126000000000000011000512512.0

---恢复内容结束---

前面的空缺是我忘了保存

2.77

使用位移运算和+- 实现乘法运算
A k=17 C=x<<4+x
B k=-7 C=x-(x<<3)
C k=60 C=x<<6-x<<2
D k=-112 就不做了

2.78

写出具有如下原型的函数

int divide_power2(int x,int k){
    int w=sizeof(int)*8;
    int mask=x>>w-1;
    int bios=(1<<k)-1;
//  printf("%d",bios);
    return(x+bios&mask)>>k;
}

使用负数掩码添加bios的技巧

2.79

计算函数

int mul3div4(int x){
    x=x<<1+x;
    return divide_power2(x,2);
}

//这个版本只需要先乘然后除就可以了

2.80

新的版本不要求溢出

int threefourths(int x){
    int b1=divide_power2(x,1);
    int b2=divide_power2(x,2);
    return b1+b2;
}
//这个版本可以改进的,所有的掩码应该是一样的,我就不写了

2.81

A. 1[w-n]0[n]: ~((1<<n) - 1)
B. 0[w-n-m]1[n]0[m]: ((1<<n) - 1) << m

2.82

A x<y == -x>-y
对于大部分正负合理的数是对的 ,但是极端数当 x等于 INT_MIN时不对
B (((x+y)<<4)+y-x)==17y+15x 只是加减构成了阿贝尔群 , 这样的等是没有问题
C ~x+~y+1= ~(x+y) 这个因该是对的 有这个式子 -x=~x+1 恒成立
D 对的 (ux-uy)==-(unsigned)(y-x)
E ((x>>2)<<2)<=x 因该是对的 最后的两位被归零了 其余的位不变

2.83

A. 令x为无穷序列表示的值,可以得到x*2^k = Y + x。 所以 x = Y/(2^k - 1)。 B. (a)1/7, (b)9/15 = 3/5, (c)7/63 = 1/9
表示无穷的方法

2.84

通过符号位来判断float的大小这种方法是有非常好的性质,因为浮点数的自然顺序就是如此
还是漏掉了一种方法。
有四种不同的情况
一正一负
都是零
同正
同负
((ux<<1)==0 && (uy<<1)==0) || (!sx && sy) || (!sx && !sy && ux >= uy) || (sx && sy && ux <= uy);

2.85

有k位指数 n位小数
写出阶码E,尾数M,小数f,和值V得公式

数7.0

E =10011 (共k位)
f =11000共n位
尾数
###够被准确描述的最大奇整数###
小数f 1111(全一 共N位 )
阶码 10011 (值是n) 2^(n-1) 这么大
值因该是
11111111 有n+1个 1
这个值是 2^n -1

最小的规格化数的倒数

最小的规格化数
阶码
00000001 -2^(k-1) +2// 1-bios bios=2^(k-1)-1
小数
0000000 全零代表 1
值 2^{-2^(k-1)+2}

取导之后是
2^{ 2^(k-1) -2}
阶码是 11101 只有第1位是0 // 值应该是 2^k-1 -2 + bios
2^(k-1)
尾数是全零表示1

阶数的符号表示不是补码表示,进行计算的时候要带上bios
2^k-1 -1 这个是bios 换句话讲阶数等于0是这样的 01111111 大于零的阶数首位必定是1

2.86

精度扩展的问题
80位字节下浮点数的一些特值
1 个符号位
15个阶码位
1个整数位 规格化数位1 非规格化数值为零
63个小数位
最小的 正非规格化数

2^( -2^(14) +###2### ) * 2^(-63)
//非规格化数阶数为1- bios 为了平滑的过渡
3.64510^(-4951)
最小的正规格化数
2^(-2^14 +2 )
最大的规格化数
(2-2^(-63))
2^{2 ^(14))}

2.87

在 一个符号位 五个阶码位 10个尾数位 时填表

描述HexMEVD
-0800000-0*
最小的大于2的值40010000000001100002 +2^-9*
5126000000000000011000512512.0
最大非规格化数7fff111111111111111(2 - 2^-10 )*2^16*
-∞fc00****

M 应该是小数值
E 应该是阶码的值,我就不再改了

2.88

浮点数的转换

1 01110 001-9/161 0110 0010-9/16
0 10110 1014160 1110 1010416
1 00111 110-9/10240 0000 0111-7/1024
0 00000 1015*2^120 0000 00000
1 11011 000-2^121 1111 0000-∞
0 11000 1003*2^80 111 1111(2-2^4)*2^8

2.89

另外在32位的机子上double 和 flaot 是使用了80位的扩展精度(我的机子上只有longdouble 是80 位 的)
喜闻乐见的找错误环节
int x=random()
double dx=(double)x
A (float)x==(float)dx 错的,单精度浮点数误差 最多表示一个数最高位1和最低的1相差不超过24位的数 ,超过这个范围没有办法表示了
B dx-dy ==(double)(x-y) 显然是错的
C (dx+dy)+dz==dx+(dy+dz) 经典的错误 浮点数的结合律会被舍入规则坑掉的
D dx/dx=dz/dz 其中一个是0的话有可能出来Nan的

2.90

偷个懒就是判断一些可以有效表示的范围

2.91-2.97

实现在 flaot_bits 上的函数 我就先不写了

转载于:https://www.cnblogs.com/sfzyk/p/7619897.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值