第三十三题:循环者遇到了狼人
i != 0 && i == -i ,定义i,使表达式结果为true
public static void main(String[] args) {
int i = Integer.MIN_VALUE;
System.out.println(i != 0 && i == -i);
}
i不能为0,还需要等于-i。在java中对一个数值取负值,需要对每一位取反,再加一。这时,int的最小值Integer.MIN_VALUE补码为0x80000000,取反后为0x7fffffff,还要加一为0x80000000。最终发现Integer.MIN_VALUE的相反数为自身。当使用Math.abs这个方法对Integer.MIN_VALUE取绝对值,也会发现等于自身。
由于int的取值范围是-2^31到2^31-1,-2^31的相反数为2^31,但是int最大值为2^31-1,会产生溢出,结果是最大值加1,溢出后是最小值,也就是本身了。
当然,使用int存储2^31,也会溢出为int最小值,只要溢出为int最小值,就能满足上面的条件,所以说这可以看作是个取模的运算。i%(2^31)==0就能满足.
第三十四题:被计数击倒了
public static void main(String[] args) {
final int START = 2000000000;
int count = 0;
for(float f = START;f < START + 50;f++) {
count++;
}
System.out.println(count);
System.out.println(ChapterUtil.getIEE754FromFloat(START));
System.out.println(ChapterUtil.getIEE754FromFloat(START+50));
System.out.println(Math.ulp(START));
}
//控制台打印:
//0
//4eee6b28
//4eee6b28
//128.0
这一题与第28题类似,浮点数太大的话,与它下一个浮点数之间间隔不只是1,而是一个ulp,这题的ulp是128,START+50与START其实是一样的数。没有执行循环体,直接输出count了。
第三十五题:一分钟又一分钟
public static void main(String[] args) {
int minutes = 0;
for(int ms = 0; ms < 60*60*1000; ms++) {
if(ms % 60*1000 == 0)
minutes++;
}
System.out.println(minutes);
}
//控制台输出:
//60000
这道题考察了运算符的优先级与结合性,在java中%与*是相同的优先级,但是结合性是从左到右,所以会先计算ms%60,再将结果*1000。
第三十六题:优柔寡断
public static void main(String[] args) {
System.out.println(decision());
}
static boolean decision() {
try {
return true;
}finally {
return false;
}
}
//控制台打印:
//false
程序的意外结束:在执行语句中抛出异常,或封闭区域执行break或continue,又或者执行return语句。
在try-finally语句中,先执行try语句块的内容,不管是否正常结束,还是意外结束,都会执行finally块中的内容。在try和finally中都有return,最后会执行finally的return,而不会执行try内的return。如果try有return,而finally没有,那么finally块只是副本,不会修改return的值。
public static void main(String[] args) {
System.out.println(decision());
}
static int decision() {
int i = 0;
try {
return i;
}finally {
i = 10;
System.out.println("finally块内i:"+i);
}
}
//控制台输出:
//finally块内i:10
//0