(构造笔记)MIT reading部分学习心得

MIT reading部分学习心得

静态检查

冰雹序列

下面的例子,就是根据冰雹序列的规律给出的,根据下面的例子,尝试寻找冰雹序列的规律:

2 ,1
3 ,10, 5 ,16, 8, 4, 2, 1
2n, 2n-1 ,, 4, 2, 1
5, 16, 8, 4, 2, 1
7, 22, 11, 34, 17, 52, 26, 13, 40,? (会停止吗?)
计算冰雹序列

下面为计算冰雹序列的java代码:

int n = 3;
while (n != 1) {
    System.out.println(n);
    if (n % 2 == 0) {
        n = n / 2;
    } else {
        n = 3 * n + 1;
    }
}
System.out.println(n);
心得

冰雹序列就是根据所给的序列,从正整数n开始,如果n是偶数,则下一个数是n/2,否则下一个数是3n+1,直到n等于1。由于存在3n+1这种变化,所以序列元素的大小可能会忽高忽低——这也是“冰雹序列”名称的来历,冰雹在落地前会在云层中忽上忽下。那么所有的序列都会最终“落地”变到1吗,这个问题值得大家深思。

静态类型

Java是一种静态类型语言。所有变量的类型在编译时(程序运行之前)是已知的,因此编译器也可以推断出所有表达式的类型。例如a和b被声明为int类型,那么编译器就会得出a+b也是int类型的结论。

静态类型是一种特殊的静态检查,可以避免bug的产生。其中静态类型就阻止了一大部分和类型相关的bug——确切点说,就是将操作符用到了不对应的类型对象上。如果你写了一行代码如下:

"5"*"6

那么静态类型检查就会在你编辑代码的时候发现这个bug,而不是等到你编译后运行程序的时候。

静态检查、动态检查、无检查

编程语言通常能提供以下三种自动检查的方法:

静态检查: bug在程序运行前发现
动态检查: bug在程序运行中发现
无检查: 编程语言本身不帮助你发现错误,你必须通过特定的条件(例如输出的结果)检查代码的正确性。

很显然,静态检查的效果远好于动态检查,更好于无检查。
下面分析一下三种检查通常会发现什么bug。

静态检查

语法错误:例如忘记标点符号或者写错关键词。在python中,如果在编程时,有多余的缩进或者换行,就会被检查出来。
错误的名字:如Math.sine(2). (应该是 sin.)
参数的个数:如 Math.sin(30, 20).
参数的类型:如Math.sin(“30”).
错误的返回类型 :例如一个声明返回String类型函数return 10;

动态检查

非法的变量值:例如整型变量x、y,表达式x/y 只有在运行后y为0才会报错,否则就是正确的。
无法表示的返回值:例如最后得到的返回值无法用声明的类型来表示。
越界访问:例如在一个字符串中使用一个负数索引。使用一个null对象解引用。

心得

静态检查可以检测与变量类型相关的错误。正如上面提到过的,语法错误、错误的名字、参数的个数等。动态类型检查倾向于特定值才会触发的错误,例如除零错误和越界访问,编译器是不会在编译的时候报错的,只有在运行的时候才会报错。
所以我们在编写代码的时候,首先需要注意的就是要减少静态错误的出现,注意代码的书写规范,以及书写格式,提高我们的编程效率。

练习

下面有一些基于java的代码示例,判断它是以上描述的哪种错误。

//示例1
int sum=0;
for(i=0;i<=100;i++)
{
    sum=sum+i
}
System.out.println(sum);

示例1为静态错误,编写代码时漏写“ ; ”

//示例2
int sum=10;
int i=0;
int average=sum/i;

示例2为动态错误,编写代码时出现除0错误。

//示例3
int a=100000;
int b=a*a;
System.out.println("a的平方为:"+b);

示例3无报错,但出现错误的结果。

数组和聚集类型

现在把冰雹序列的结果存储在数据结构中。在Java中有两种常用的线性存储结构:数组和列表。

数组是一连串类型相同的元素组成的结构,而且它的长度是固定的(元素个数固定)。例如,我们声明一个int类型的数组:

 int a[] = new int[50];

下面基于数组,编写冰雹序列存储代码:

int a[] = new int[50];  
int i = 0;
int n = 3;
while (n != 1) {
    a[i] = n;
    i++;  
    if (n % 2 == 0) {
        n = n / 2;
    } else {
        n = 3 * n + 1;
    }
}
a[i] = n;
i++;

我们可以这样声明列表:

List<Integer> list = new ArrayList<Integer>();

下面基于列表,编写冰雹序列存储代码:

List<Integer> list = new ArrayList<Integer>();
int n = 3;
while (n != 1) {
    list.add(n);
    if (n % 2 == 0) {
        n = n / 2;
    } else {
        n = 3 * n + 1;
    }
}
list.add(n);

比较上述两种存储方法,思考异同。

心得

我们会发现基于数组的冰雹序列存储有一些问题,我们并不知道冰雹序列的长短,就将存储冰雹序列的存储结构定义为数组,且数组的长度只有50,如果我们给出的冰雹序列足够长,系统就会报错,像这样的bug称为越界访问。
而列表类型很好的改善了这个问题,因为列表会自动扩充以满足新添加的元素,所以就不有再担心越界问题。
我们在编程的时候,要根据不同的情景及要求选择不同的存储结构,既要使代码简介易懂,还要尽可能减少不必要的错误。

迭代

对于在一个序列结构(例如列表和数组)遍历元素,Java和Python的写法差不多:

int max = 0;
for (int x : list) {
    max = Math.max(x, max);
}

Math.max() 是一个Java API提供的函数。

方法

Java中,声明通常必须在一个方法中,而每个方法都要在一个类型中,下面是冰雹序列的程序:

public class Hailstone {
    /**
     * Compute a hailstone sequence.
     * @param n  Starting number for sequence.  Assumes n > 0.
     * @return hailstone sequence starting with n and ending with 1.
     */
    public static List<Integer> hailstoneSequence(int n) {
        List<Integer> list = new ArrayList<Integer>();
        while (n != 1) {
            list.add(n);
            if (n % 2 == 0) {
                n = n / 2;
            } else {
                n = 3 * n + 1;
            }
        }
        list.add(n);
        return list;
    }
}

心得

MIT reading部分的Static Checking主要讲述了静态检查以及几种存储数据结构。
首先引入冰雹序列,先讲了冰雹序列的定义以及简单的输出代码。
然后通过静态检查、动态检查以及无检查的对比,让我们更加熟悉他们的异同。即:
静态检查可以检测与变量类型相关的错误。例如语法错误、错误的名字、参数的个数等。动态类型检查倾向于特定值才会触发的错误,例如除零错误和越界访问,编译器是不会在编译的时候报错的,只有在运行的时候才会报错。
所以我们在编写代码的时候,首先需要注意的就是要减少静态错误的出现,注意代码的书写规范,以及书写格式,提高我们的编程效率。
然后对比了数组和聚集的不同,以及在编写冰雹序列代码时的不同,
需要注意的是,数组有长度(即元素的个数),在存储不定量元素时,可能会出现越界的问题。而列表会自动扩充以满足新添加的元素,所以就不用再担心越界问题。
我们在编程的时候,要根据不同的情景及要求选择不同的存储结构,既要使代码简介易懂,还要尽可能减少不必要的错误。

[本文参考自]
(http://web.mit.edu/6.031/www/sp20/classes/01-static-checking/)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值