您的位置:首页 > 编程语言 > Java开发

[Java] 作业3答疑

2016-03-28 21:19 267 查看
Q5

作业1. Q5.

Q9


建议对前缀++和后缀++仍有疑虑的同学阅读这篇博文:[Java] i++与++i的区别(后缀++与前缀++)

int m = 3, n = 5, k = 0;
while ((m++) < (--n))
++ k;
第一次执行m++ < --n

m++

    - m=4, 返回m的旧值3.

--n

    - n=4, 返回n的新值4.

3 < 4 成立,++ k, k变成1.

第二次执行m++ < --n

m++

    - m=5, 返回4

--n

    - n=3, 返回3

4 < 3 不成立,循环结束。

Q11

-- i --; // 这里语法错误,题目不对

Q12 

根据语法,case后面需要跟break, 才会跳出switch语句,否则将依次执行正确case后面的所有语句。所以此题的运行结果是:

int i = 10, j = 18, k = 30;
switch(j - i) {
case 8:
k ++;   // k = 31
case 9:
k += 2; // k = 33
case 10:
k += 3; // k = 36
default:
k /= j; // k = 2
}


Q13

for (int i = 0, j = 1; j < 5; j += 3)
i = i + j;
初始化:
    - i = 0

    - j = 1

第一次迭代:

    - j < 1成立,开始执行

    - i = i + j = 1

    - j = j + 3 = 4

第二次迭代:

    - j < 5成立,开始执行

    - i = i + j = ?

    - j = ?

第三次迭代:

    - ...

注意到,j < 5不成立,将中止循环,此时i的值即为结果。

Q32

boolean even = false;
if (even = true)
System.out.println("It is even!");
根据Java Language Specification -- 15.1 Evaluation, Denotation, and Result, 一个表达式的返回值可能是:

    - A variable(一个变量)

        - 假如a是一个变量的名字,那么表达式a(单个变量名就可以作为一个表达式), 可以认为它返回的是变量a

    - A value(一个值)

        - 比如说表达式5, 可以认为它返回的值是5.

    - Nothing (the expression is said to be void, 我们称这个表达式是void)

对于赋值表达式(assignment expression, 亦即"="操作符),以v = a为例,它会做两件事:

    1. 将a的值赋值给变量v

    2. 返回v的值

所以对于 if (even = true), 这里发生了三件事:

    1. 将true赋值给even

    2. 将even的值(亦即true)返回

    3. if接收到这个返回值true,认为条件成立,执行分支内的语句(亦即println)

Q33, Q34 同 Q32

Q71

0. 

解决这题的关键,是理解floating-point是有误差的,无法被精确表示的。

1. 什么是floating-point(浮点数)

wikipedia -- Floating point所示,这里的floating point指的是浮点数,非正式地可以理解成“小数”.

在Java中,无论是float还是double类型,它们都是浮点,区别是在于:

    - float是32位的单精度(type: single, wikipedia上有写)

    - double是64位的双精度浮点(type: double, wikipedia上有写)

所以题目中所说的floating-point指的不是特定的某种类型(float or double), 指的是浮点数。

2. 为什么浮点数无法被精确表示

2.1 浮点的二进制表示

因为计算机采用了同一种特殊的方式,用来表示浮点数。

直观的,我们考虑 六又八分之五(6.625, 这个网站不能写数学公式...)这个分数。它的二进制表示是

    110.101 (左边是6,小数点右边是5(代表5/8))

进一步,它可以写成

    0.110101 * (2^3)

所以那么在机器中,如果我们用32位来表示它,那么它的二进制表示是:

    0 1000_0001 1010_1000_0000_0000_0000_000

        1) 第一个0, 代表这是一个正数

        2) 中间8个bit, 我们管它叫significan, 十进制表示是129

        3) 最后23个bit, 叫做precision

我们可以用这三段数字翻译出6.625:

    + 1.precision * 2^(significan - 127)

    也就是 + 1.10101 * 2 ^ (129 - 127) = 110.101, 也就是6.625. 

感兴趣但仍不理解的同学,可以去群里下载我上传的《Introduction to Computing Systems》,原书39页 Chapter 2.7 Other Representation 中有讲到这个6.625的例子。OS: 作者Yale Patt几乎每年暑假都有来浙大讲课,讲得通俗易懂,据说他有时会跟高中生讲这门课。即使你不是CS专业也可以旁听或选课(要花费一些精力)。大三时,学院有邀我去当他的助教,我当时还在温哥华就没回来:D

2.2 这样表示的优点 -- 能表示一定范围内的小数

用32位就可以表示大概是[2^-126, 2^127]的小数了,而且这个范围比32位int所表示的大概是[-2^31, 2^31]的范围大得多。

2.3 这样表示的缺点 -- 精度不够

在2.1中,6.625刚好可以用110.101来表示六又八分之五。但大家考虑0.1就会发现,它是无法被精确表示的,这个表示法,只能利用23位的precision尽量得去近似这个小数。

所以浮点用等于号来比较,经常是不能获得数学中相等的情况的——因为这两个数的32位二进制可能在有效数字最后几位有所差异。

3. 一个例子

public class DoubleTest {
public static void main(String[] args) {
for (double d = 0; d < 1.0; d += 0.1)
// 每次打印d的值
System.out.println(d);
}
}
打印结果:



大家可以发现,d每次增加0.1, 但是有些时候在最后几位还是会出现非零的情况的。

所以结论就是一开始和大家说的“0. floating-point是有误差的,是无法被精确表示的”.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java