java编程思想与算法设计

本文探讨了Java编程中的一些关键概念,包括字符串常量的处理,浮点数的不精确存储,字符转换,Scanner方法的区别,异或运算符的应用,以及如何在循环中处理浮点数误差。举例说明了最小化数值误差的方法,并提醒在循环控制中避免使用浮点值比较。最后提到了使用确认对话框在循环控制中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. java中的字符串常量不能跨行,例如以下代码将不会通过编译:

public class MyString{
       public static void main(String[] args){
              System.out.println("Hello 
                     World");
       }
}

这也就是为什么要使用“+”运算符进行字符串的连接。

2. java中的浮点数都不是精确存储的,例如:

System.out.println(1.0 - 0.9);	//运行结果0.09999999999999998而不是0.1
3. Unix时间戳(Unix epoch),因为Unix操作系统是在1970年正式发布的。


利用乘法和取余我们可以很方便地得到格林尼治时间:

long toalMilliseconds = System.currentTimeMillis();
	long totalSeconds = toalMilliseconds / 1000;
	long totalMinutes = totalSeconds / 60;
	long totalHours = totalMinutes / 60;

	int currentSeconds = (int) (totalSeconds % 60);
	int currentMinutes = (int) (totalMinutes % 60);
	int currentHours = (int) (totalHours %24);

	System.out.println("格林尼治时间"+currentHours + ":" + currentMinutes + ":"
		+ currentSeconds);
4. 自增和自减也可以用在char类型的数据上,例如:

char c = 'A';
	System.out.println(++c);
将打印出B

5. 所有的数值运算符都可以用在char型操作数上,如果其中一个操作数是数字或者字符的话,那么char型操作数会自动转化成一个数字;如果其中一个操作数是一个字符串,该字符就会与字符串进行连接。

System.out.println('A'+'0');	//结果是113=65+48
	System.out.println('A'+1.2);	//结果是66.2=65+1.2
	System.out.println('A'+"字符串");	//结果A字符串,与字符串进行了连接
Tips:关于小写字母ch转化成大写字母可以采用以下的算法:

(char) ('A' + ch - 'a')——ch表示需要转化成大写字母的小写字母。

6. Scanner的next()方法和nextLine()方法的区别:

- next()方法读取以空白字符结尾的字符串(如:' '、'\f'、'\r'、'\n'、'\t')

- nextLine()方法可以读取一整行文本。

System.out.println("输入3个字符串");
	Scanner scanner = new Scanner(System.in);
	String s1 = scanner.next();
	String s2 = scanner.next();
	String s3 = scanner.next();
	System.out.println("s1 = " + s1 + " ,s2 = " + s2 + " ,s3 = " + s3);

运行结果:


System.out.println("输入字符串:");
	Scanner scanner = new Scanner(System.in);
	String s = scanner.nextLine(); // 读取一行
	System.out.println("s = " + s);

运行结果:


特别警告:为了避免输入错误,不要在nextByte()、nextShort()、nextInt()、nextLong()、nextFloat()、nextDouble()和next()之后使用nextLine()。将会抛出java.util.InputMismatchException。

7. 异或运算符^不仅仅可以用于位运算也可以用于逻辑运算:

System.out.println(false^false); //异或运算也能够用于逻辑运算
	System.out.println(false^true);
	System.out.println(true^false);
	System.out.println(true^true);
运行结果:


利用异或的真值表可以进行以下的判定(一个数能够被2整除但是不能被3整除,或者能够被3整除但是不能被2整除——也就是说该数当且仅能被2和2其中的一个整除,利用异或可以简化两个判断为一个)

System.out.println("#");
	Scanner scanner = new Scanner(System.in);
	int number = scanner.nextInt();
	if (number % 2 == 0 ^ number % 3 == 0) {           //异或运算简化编程
	    System.out.println(number + "能够被2和3中的一个整除!");
	}

8. 在循环控制当中不要使用浮点值来比较是否相等。因为浮点值都是某些类的近似值,使用它们很可能导致不精确的循环次数和不准确的结果。考虑下面计算1+0.9+0.8+……+0.1的代码:

double item = 1, sum = 0;
	while (item != 0) { // 死循环
	    sum += item;
	    item -= 0.1;
	}
	System.out.println("sum = " + sum);
变量item从1开始,每执行一次循环体就减去0.1.当item变为0的时候循环就应当终止。但是,因为浮点数在算术上是近似的,所以不能确保item会变成真正的0.从表面来看,这个循环似乎没有问题,但是实际上他是一个无限循环!


9. 如果省略for循环中的循环等待条件,则隐含地认为循环继续条件为true。因此,下面的a、b2个语句是等价的,他们都是无限循环。但是为了避免混淆,最好还是使用c中的等价循环。

a:

for (;;) {
	    // Do something
	}
b:

for (; true;) {
	    // Do something
	}
c:

while (true) {
	    // Do something
	}

最小化数值误差

涉及浮点数的数值误差总是不可避免的,以下实例将讲解如何最小化这种误差。

计算0.01+0.02+0.03+……+1的数列的和。

public class TestSum {

    public static void main(String[] args) {

	System.out.println("该程序将计算0.01+0.02+0.03+……+1的和");
	float sum = 0;
	for (float i = 0.01f; i <= 1.0f; i += 0.01f) {
	    sum += i;
	}
	System.out.println("sum = " + sum); // 用数学公式应该得到50.5但是实际结果是50.499985
    }

}

sum的精确结果应该是50.50,但是以上程序计算的结果是50.499985。这个结果是不精确的,因为计算机使用的固定位数表示的浮点数,因此不能够精确地表示某些浮点数。如以下程序所示,将程序中的float类型改变成double类型,可以看到精度有一点点的改善(因为double类型采用的是64位而float类型采用的是32位)。

public class TestSum {

    public static void main(String[] args) {

	System.out.println("该程序将计算0.01+0.02+0.03+……+1的和");
	double sum = 0;
	for (double i = 0.01; i < 1.0; i += 0.01) {
	    sum += i;
	}
	System.out.println("sum = " + sum); // 用数学公式应该得到50.5但是实际结果是49.50000000000003
    }

}

为了解决这个问题,使用整数计数器以确保所有的数字都被加入到sum中,下面是一个新的循环:

public class TestSum {

    public static void main(String[] args) {

	System.out.println("该程序将计算0.01+0.02+0.03+……+1的和");
	double sum = 0;
	int count = 1;
	double currentValue = 0.01;
	for (int i = 0; i < 100; i++) {
	    sum += currentValue;
	    currentValue += 0.01;
	    System.out.print(currentValue + "\t"); // 打印i值
	    if (count++ % 5 == 0) {
		System.out.println();
	    }
	}
	System.out.println("sum = " + sum); // 用数学公式应该得到50.5但是实际结果是49.50000000000003
    }

}
运行结果:

这个循环结束后,sum的值是50.50000000000003,这个循环从小到大添加数字。如果使用下面的方法从大到小添加(即:1.0+0.99+0.98+……+0.02+0.01)会发生什么情况?

public class TestSum {

    public static void main(String[] args) {

	System.out.println("该程序将计算0.01+0.02+0.03+……+1的和");
	double sum = 0;
	int count = 1;
	double currentValue = 1.0;
	for (int i = 0; i < 100; i++) {
	    sum += currentValue;
	    currentValue -= 0.01;
	    System.out.print(currentValue + "\t"); // 打印i值
	    if (count++ % 5 == 0) {
		System.out.println();
	    }
	}
	System.out.println("sum = " + sum); // 用数学公式应该得到50.5但是实际结果是50.49999999999995
    }

}
运行结果:

在这个循环结束之后,sum的值是50.49999999999995。从大到小添加数字没有从小到大添加数字得到的值精确——这种现象是有限精度算术的产物。如果结果值要比变量所能存储的容量更高的精度,那么添加一个非常小的数给一个非常大的数可能没有什么影响。例如:

public class TestSum {

    public static void main(String[] args) {
	System.out.println(100000000.0 + 0.000000001); // 结果是:1.0E8
    }

}

使用确认对话框控制循环

使用确认对话框可以实现一个标志值控制的循环。答案Yes或者No将决定是继续还是终止这个循环。这个循环的模板看起来如下:
	int option = JOptionPane.YES_OPTION;
	while (option == JOptionPane.YES_OPTION) {
	    System.out.println("继续循环");
	    option = JOptionPane.showConfirmDialog(null, "继续?");
	}
下面是一个计算和的GUI程序:
import javax.swing.JOptionPane;

public class SentinelvalueUsingConfirmDialog {

    public static void main(String[] args) {
	int sum = 0;

	// 一直读取数据直到用户选择否
	int option = JOptionPane.YES_OPTION;
	while (option == JOptionPane.YES_OPTION) {
	    // 读下一个数据
	    String dataString = JOptionPane.showInputDialog("输入值:");
	    int data = Integer.parseInt(dataString);
	    sum += data;
	    option = JOptionPane.showConfirmDialog(null, "继续?");
	}
	JOptionPane.showMessageDialog(null, "sum = " + sum);
    }

}
运行结果:

11. 解释一下下面的程序为什么能够运行?
 public static void main(String[] args) {
	int x = 1;
	while (x > 0) {// 不是死循环
	    x++;
	}
	System.out.println("x = " + x);
    }
程序刚开始看1>0应该是恒成立,所以循环应该是死循环,但是x有增量,整数是有范围的,一旦超出范围就会产生溢出,所以正数相加最后会变成负数从而满足循环的终止条件(这一点要特别注意)。以上程序的运行结果是Integer.MIN_VALUE = -2147483648,因为程序一直会加到整数的最大值,然后整数溢出就变成了最小值。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值