Java学习之路(五)--Thinking in Java
写程序要细心,遇到bug要善于排查。
今天在用Java写几个小程序的时候,由于极力追求优化与功效,忽视了一个小小的细节问题。但最终找到了bug并且解决了它。
我们都知道,在使用for循环的时候,比如:
for(int i = 0; i < n; i++){...}
我们一般都这儿写。但是仅仅这样是不够的,因为这段语句还可以进行优化。比如i<n,就不如直接判断i!=n,这样在计算机内部可以节省运算时间。还有,i++还可以改写成++i,因为i++需要计算机保存i之前的值之后再+1,++i直接让i+1并没有临时变量。可是,正因为如此,一个小小的不易察觉的bug发生了。
原题目很简单,就是求整数a,b之间的全部素数。开始我是这么写的:
import java.io.*;
import java.util.*;
public class number2 {
public static void main(String[] args) throws IOException{
int begin, end;
String str;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
str = br.readLine();
begin = new Integer(str);
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
str = br1.readLine();
end = new Integer(str);
for (; begin != end; ++begin){
boolean b = true;
for(int i = 2; i != Math.sqrt(begin); ++i){
if(0 == begin % i){
b = false;
break;
}
}
if(b)
System.out.println(begin);
}
}
}
注意仔细看代码着色部分,乍看之下没什么不对,追求了性能。可是运算的结果却是令人大吃一惊。求101到200的素数,出现121,169两个数。经过我仔细排查之后发现原来bug正是出在这里:Math.sqrt()是double,i是一个int,在与double的比较过程中是永远不相等的。或者我们把着色语句强制转换成(int),或者,改写成 i<Math.sqrt(begin)。
修改之后成功运行,代码如下:
1 import java.io.*; 2 import java.util.*; 3 public class number2 { 4 public static void main(String[] args) throws IOException{ 5 int begin, end; 6 String str; 7 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 8 str = br.readLine(); 9 begin = new Integer(str); 10 BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in)); 11 str = br1.readLine(); 12 end = new Integer(str); 13 for (; begin != end; ++begin){ 14 boolean b = true; 15 for(int i = 2; i < Math.sqrt(begin); ++i){ 16 if(0 == begin % i){ 17 b = false; 18 break; 19 } 20 } 21 if(b) 22 System.out.println(begin); 23 } 24 } 25 }
关于代码中出现的输入输出流以后再做讨论。