Liam的计组学习历程(一):第一次作业(2015.10.20)

第一次作业

第一题:

1.验证X的平方是否大于等于零
首先在VS上创建好C++工程,编写代码如下:

#include "stdafx.h"
#include "iostream"
#include "float.h"

using namespace std;

const short SMAX = 32767, SMIN = -32768, SNOR = 100, SMAX_RES = SMAX*SMAX,SMIN_RES = SMIN*SMIN,SNOR_RES=SNOR*SNOR;
const float FMAX = FLT_MAX, FMIN = FLT_MIN, FNOR = 100,FMAX_RES=FMAX*FMAX,FMIN_RES=FMIN*FMIN,FNOR_RES=FNOR*FNOR;


int _tmain(int argc, _TCHAR* argv[])
{
    cout << "SHORT型:" << endl;
    if (SMAX_RES < 0){
        cout << SMAX << " 的平方小于零!" << endl;
    }
    else if (SMAX_RES == 0){
        cout << SMAX << " 的平方等于零!" << endl;
    }
    else{
        cout << SMAX << " 的平方大于零!" << endl;
    }
    if (SMIN_RES < 0){
        cout << SMIN << " 的平方小于零!" << endl;
    }
    else if (SMIN_RES == 0){
        cout << SMIN << " 的平方等于零!" << endl;
    }
    else{
        cout << SMIN << " 的平方大于零!" << endl;
    }
    if (SNOR_RES < 0){
        cout << SNOR << " 的平方小于零!" << endl;
    }
    else if (SNOR_RES == 0){
        cout << SNOR << " 的平方等于零!" << endl;
    }
    else{
        cout << SNOR << " 的平方大于零!" << endl;
    }

    cout << "FLOAT型:" << endl;
    if (FMAX_RES < 0){
        cout << FMAX << " 的平方小于零!" << endl;
    }
    else if (FMAX_RES == 0){
        cout << FMIN << " 的平方等于零!" << endl;
    }
    else{
        cout << FMAX << " 的平方大于零!" << endl;
    }
    if (FMIN_RES < 0){
        cout << FMIN << " 的平方小于零!" << endl;
    }
    else if (FMIN_RES == 0){
        cout << FMIN << " 的平方等于零!" << endl;
    }
    else{
        cout << FMIN << " 的平方大于零!" << endl;
    }
    if (FNOR_RES < 0){
        cout << FNOR << " 的平方小于零!" << endl;
    }
    else if (FNOR_RES == 0){
        cout << FNOR << " 的平方等于零!" << endl;
    }
    else{
        cout << FNOR << " 的平方大于零!" << endl;
    }

    return 0;
}

输出结果如下:

同时为了更清楚地观察数据,我在VS中设置了监控,结果如下:

结果分析:
从程序结果和监控结果中,我们不难看出,short型变量和float型变量的最小值的平方结果都变为了0,我认为这是因为在计算的过程中,数据发生了溢出,而在存储时,仍会截取满足数据类型要求的后几位来存储,所以显示出来的结果就会是0,与我们正常计算的结果存在差异。

2.验证(X+Y)+Z 是否等于X+(Y+Z)
首先编写代码如下:

#include "stdafx.h"
#include "iostream"
#include "float.h"

using namespace std;

const short S1 = 32767, S2 = -32768, S3 = 100;
const float F1 = 0.319, F2 = 1.000000001, F3 = 3.14;


int _tmain(int argc, _TCHAR* argv[])
{
    if (((S1 + S2) + S3) == (S1 + (S2 + S3))){
        cout << "SHORT:equal!" << endl;
    }
    else{
        cout << "SHORT:not equal!" << endl;
    }
    if (((F1 + F2) + F3) == (F1 + (F2 + F3))){
        cout << "FLOAT:equal!" << endl;
    }
    else{
        cout << "FLOAT:not equal!" << endl;
    }
    return 0;
}

得到运行结果:

分析:
从结果中我们可以看出SHORT型的结果是相同的,而FLOAT型的结果则不同。我认为这是由于计算机在进行计算时在处理完第一步后,有可能将得到的结果先进行一下处理,如根据两个加数保留一定的有效数字,因此由于运算顺序的不同,每次的加数可能不同,进而导致了最终浮点数的有效数字保留的不同,而产生了上的结果。

实验二:

首先我在VS中编写了一次代码:

#include "stdafx.h"
#include "iostream"

using namespace std;

double fun(int i);

int _tmain(int argc, _TCHAR* argv[])
{
    double result;
    result = fun(0);
    cout << "Input:0, 结果:" << result << endl;
    result = fun(1);
    cout << "Input:1, 结果:" << result << endl;
    result = fun(2);
    cout << "Input:2, 结果:" << result << endl;
    result = fun(3);
    cout << "Input:3, 结果:" << result << endl;
    result = fun(4);
    cout << "Input:4, 结果:" << result << endl;
    return 0;
}
double fun(int i){
    volatile double d[1] = { 3.14 };
    volatile int a[2];
    a[i] = 1073741824;
    return d[0];
}

运行后发生错误:

点击继续后结果如下:

看到结果相同,我想到了VS带有越界警告的功能,于是我又在CodeBlocks上再一次实验了一次:

#include <iostream>
#include<cstdio>
using namespace std;

double fun(int i);

int main()
{
    double result;
    result = fun(0);
    cout << "Input:0, 结果:" << result << endl;
    result = fun(1);
    cout << "Input:1, 结果:" << result << endl;
    result = fun(2);
    cout << "Input:2, 结果:" << result << endl;
    result = fun(3);
    cout << "Input:3, 结果:" << result << endl;
    result = fun(4);
    cout << "Input:4, 结果:" << result << endl;
    return 0;
}

double fun(int i){
    volatile double d[1] = { 3.14 };
    volatile int a[2];
    a[i] = 1073741824;
    return d[0];
}

这一次运行后依旧得到了警告:

之后的运行结果为:

 

分析:
对于这一部分的内容,我也并不是很了解,所以请教宿舍中去年学习过计组课程的同学,经过同学们的讲解我有了如下的认识:
首先是d和a在内存中的存储方式,他们应当是存储在堆中,而堆是由上向下进行内容的写入,大致可以画出如下的示意图:

这样根据codeblocks中的运行结果,我们可以看出,前三次的结果都是正确的,实际上,我们可以很简单的知道,前两次的结果一定是正确的,因为他修改的是a[0]与a[1]的值。而第三次实际上也是有一些问题的,它实际上已经进入了d[0]的内存范围,只不过因为double类型的数据后面有大量的小数位,这次修改只是修改了小数位的一些数值,而在输出时因为未显示那么多位小数,所以我们看到的是好像结果没有被影响。而第四次则是已经修改到了double类型的整数位,所以我们看到了结果的变化。至于最后一次测试,修改已经到了系统的内存中,因为会影响系统内存,所以codeblocks并没有让这一步执行,所以我们可以看到结果中并没有fun(4)的结果,而在VS中,因为存在越界控制的功能,所以并没有受影响,但是我们也看到了它所提示的“Stack around the variable ‘a’ was corrupted.”即提示a数组发生了越界的问题。

 

由于在课堂上还没有学习这一块的内容,以上的分析都是由我结合网上搜索到的内容以及向一些去年学习过的同学请教得出的,可能存在很多的问题,有不对的地方希望老师和同学能够告诉我,谢谢!

 

原文地址:https://www.cnblogs.com/tju-liuchang/p/4894163.html