2017-2018-1 20155213 《信息安全系统设计基础》第三周学习总结

2017-2018-1 20155213 《信息安全系统设计基础》第三周学习总结

教材学习内容总结

浏览了正章,重点学习了以下几个点

  • int,float,void*在内存中存储形式,通过P31页的代码,了解的更深一点
    • 此函数使用char*型把以上三种类型的数强制转换成按字节读取的类型,因而能更加直观的看出每个字节的位置,以及其包含的值;
    • 根据上图可以看出来我的电脑是按照大端法存储的,即高位对其低位;
  • 信息=位+上下文
    • 计算机一般都是按照冯诺依曼体系构架的,即存储形式都是以二进制形式存储的,只有0、1两种情况,具体说就是位的两种形式;
    • 如果仅仅有位的概念,那所有的存储都是无意义的,还需要对其有解释的方法,也就是在不同语境下的不同解释方法,赋予了位的意义,也就是联系上下文去解释位,解释出来的就是信息;
    • 为了更深的理解,我做了下面两种比较:
      • 相同的位但被解释出了不同的信息:教材P83页,整数3510593.00的单精度浮点数存储的十六进制表示是0x4A564504,而对于整数0x4A564504表示的十进制的值为‭1247167748比3510593大得多,虽然有着相同的位,但解释方法不同,也就会有不同的值(信息);
      • 不同的位但被解释出了相同的信息:对于0x80000001,按照int型的数来解释就是-1,但如果是unsigned型的则为‭2147483649。

教材学习中的问题和解决过程

  • 问题1:P58页练习题2.25题,运行时出现内存错误
  • 问题1解决方案:首先这个length是unsigned型的,即当length=0时,length-1即为2^32-1,而传过来的a[N]的长度远小于这个值,所以会出现内存错误,即越界,非法访问;正确修改就是把length改为int型的;

代码调试中的问题和解决过程

  • 问题1:F:\Atom_C文件\float_bits\float_bits2.c: In function 'main':
    F:\Atom_C文件\float_bits\float_bits2.c:12:6: error: invalid operands to binary ^ (have 'float' and 'unsigned int')
    f^=x;
  • 问题1解决方案:上面已经写了,说明float不能进行位运算,
  • 查阅资料后,位运算符只能用于整型操作数,即只能用于带符号或无符号的char,short,int与long类型,C语言位运算详解;
  • 解决方案就是可以使用int指针指向float型的,然后对该指针进行位操作;
  • 问题2:/tmp/ccVdmxHM.o:在函数‘float_f2i’中:float_bits.c:(.text+0x183):对‘pow’未定义的引用float_bits.c:(.text+0x1f4):对‘pow’未定义的引用;collect2: error: ld returned 1 exit status意思就是没找到pow函数。
  • 问题2解决:可是我在代码里已经声明了#include<math.h>了的,要么是在linux中没有pow这个函数,或者说是表示不同,或者就是有这个函数但不在<math.h>中。百度了问题,就是后者,gcc的数学函数都是定义在libm.so里面了linux c数学库函数

家庭作业(P97页2.96题)

  • 题目:遵循位级浮点编码规则,实现如下原型的函数:

int float_f2i(float_bits f);对于浮点数f,这个函数计算(int)f。如果f是NaN,你的函数一个向零舍入。如果f不能用整数表示(例如,超出表示范围,或者他是一个NaN),那么函数一应该返回0x80000000.测试你的函数,对参数f可以取得所有2^32个值求值,将结果与你使用的机器的浮点运算得到的结果相比较。

  • 题目分析:
    • 这题是要在没有float型的数运算的前提下,按照float编码形式读出四个字节中的数,并将此数用(int)强制转换。
    • 首先是按照float读出unsigned字节,需要四句程序,unsigned sign=f>>31;unsigned exp=f>>23&0xFF; int exp_E=(int)exp-127;unsigned frac=f&0x7FFFFF;
    • 这样之后float_bits函数就好做了,根据要求写出该函数
    int float_f2i(float_bits f)
{
    unsigned sign=f>>31;
    unsigned exp=f>>23&0xFF;
    int exp_E=(int)exp-127;
    unsigned frac=f&0x7FFFFF;
    frac=frac|0x800000;
    if(exp==0)return f&0x80000000;
    if(exp_E>30)return 0x80000000;
    if(exp_E<0)return 0;
    if(sign==1)return -(int)(frac*pow(2,exp_E-23));
    return (int)(frac*pow(2,exp_E-23));
}
    • 剩下的就是检测,但怎么获得一个float值的位信息并将其位不变换的转换成unsigned型,这就需要之前在书上P31页看到的东西,将float型按位读取,并赋值给unsigned型数,于是有了下面函数
unsigned swift(bit_transform b)
{
    unsigned un=0;
    unsigned sign[4];
    sign[0]=(unsigned)b[0];
    sign[1]=((unsigned)b[1])<<8;
    sign[2]=((unsigned)b[2])<<16;
    sign[3]=((unsigned)b[3])<<24;
    un=sign[0]|sign[1]|sign[2]|sign[3];
    printf("%x %x %x %x\n", b[3],b[2],b[1],b[0]);
    return un;
}
    • 这两个问题解决了就是测试主函数的编写了:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef unsigned float_bits;
typedef unsigned char* bit_transform;
unsigned swift(bit_transform b);
int float_f2i(float_bits f);
int main()
{
    unsigned x=0x80000000;
    float f=-9.8;
    printf("%d\n",float_f2i(swift((bit_transform)&f)));
    printf("%d",(unsigned)f);
    printf("\nHello world!\n");
    return 0;
}
    • 运行截图
  • 现在解决题目中的第二大问题就是:对参数f可以取得所有2^32个值求值。

    • 这个好解决,就是将传入的unsigned值一个一个加上去,但又出现了一个问题,就是如何检测,虽然对unsigned值可以一个一个加,但float值不可以一个一个加来改变每一位,并且float也不能通过位运算来改变每一位,此时就想到可不可以通过除法来控制每一位,经过反复测试,有这么句除法形式可以很好的操作,float f=(i*2)/pow(2,150);

    • 这样得到的从i=0取到i=223,输出值就是0x0-0x0080000;但在往后取就不会再有每位的变化了,比方说i=(224)时,位信息是0x01000000,而i=(2^24)+1,位信息依然是0x01000000,并且这种方法计算量也挺大的,故而舍弃;

    • 这时就想到可以借鉴P35页的那个showbyte()函数的构造来进行位操作从而改变每一位,借鉴其思想就是用一个unsigned型指针指向float型数,然后将该指针指向的值每每加一来实现,unsigned* un_p;float f;un_p=&f;

  • 问题都解决了,就需要运行并且比较检测了,但2^32次是真的太多了,我电脑几次跑崩了,这里就节选了三部分进行了检测,第一部分是0x0-0xFFFF(32位的前65535);第二部分5201-5239(我班学号);第三部分0xFFFF0000-0xFFFFFFFE(32位的后65535),全部写到文件里了,可以在我的码云那部分找到;

  • 截图

代码托管

(statistics.sh脚本的运行结果截图)

结对及互评

  • 结对队友20155303

  • 他的博客中值得学习的或问题:

  • 他的代码中值得学习的或问题:

  • 结对照片:

  • 结对学习内容

其他(感悟、思考等,可选)

这周就是学习了几种数值类型在计算机中的存储方式,以及解释方法,以前觉得浮点型就是规定了几位存小数点前面的数,规定了几位存小数点后面的数,一直也没有深究过,现在回头看看自己,发现我那种解释还是有点道理的,不过当真正遇到浮点型表示超过整型数时,我的解释就崩溃了。学无止境,带着自己的猜测去学习位未知的东西,总会发现有趣的东西。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 15篇 400小时
第一周 177/177 1/1 10/10
第三周 308/485 2/2 12/22

尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。

参考:软件工程软件的估计为什么这么难软件工程 估计方法

  • 计划学习时间:XX小时

  • 实际学习时间:XX小时

  • 改进情况:

(有空多看看现代软件工程 课件
软件工程师能力自我评价表
)

参考资料

posted on 2017-10-13 13:40  20155213陆忠民  阅读(312)  评论(2编辑  收藏  举报