2.12 表达式求值和操作符优先级
Java表达式的求值和数学表达式的求值是一样的。
当表达式中有多个操作符时,以下操作符的优先级规则用于确定计算的次序:
- 首先执行乘法、除法和取模运算。如果表达式中包含若干个乘法、除法和取模操作符,按照从左到右的顺序执行。
- 最后执行加法和减法运算。如果表达式中包含若干个加法和减法操作符,则按照从左到右的顺序执行。
文件名:FahrenheitToCelsius.java
问题:将华氏温度转换为摄氏温度。
import java.util.Scanner;
pubulic class FahrenheiToCelsius{
public static void main(String[] args){
Scanneer input = new Scanner(System.in);
System.out.print("Enter a degree in Fahrenheit:");
double fahrenheit = input.nextDouble();
double celsius = (5.0/9) * (fahrenheit - 32);
System.out.println("Fahrenheit " + fahrenheit + " is " + celsius + " in Celsius");
}
}
使用除法时要小心。在Java中,两个整数相除的结果为整数。5 / 9的结果是0,编码是5.0 / 9。
2.13 示例学习:显示当前时间
问题:开发一个以GMT(格林尼治标准时间)来显示当前时间的程序,以时:秒:分的格式来表示。
分析:System类中的方法currentTimeMillis 返回从GMT1970年1月1日零点开始到当前时刻的毫秒数。
可以使用这个方法获取当前时间,然后如下计算出当前的秒数、分钟数和小时数:
- 调用System.currentTimeMillis()方法获取1970年1月1日零点到现在的毫秒数 (例如:1203183068328毫秒),并存放在变量totalMi1liseconds中。
- 通过将总亳秒数totalMilliseconds除以1000得到总秒数totalSeconds (例如:1203183068328毫秒/1000=1203183068秒)。
- 通过 totalseconds%60得到当前的秒数 (例如:1203183068秒%60=8,这个值就是当前秒数)。
- 通过将totalseconds除以60得到总分钟数totalMinutes (例如:1203183068秒/60=20053051分)。
- 5)通过 totalMinutes%60得到当前分钟数 (例如:20053051分%60=31,这个值就是当
前分钟数)。 - Minutes%60得到当前分钟数 (例如:20053051分%60=31,这个值就是当前分钟数)。
- 通过将总分钟数totalMinutes除以60得到总小时数totalHours (例如:20053051分/60=334217时)。
- 通过 totalHours%24得到当前小时数 (例如:334217时%24=17,该值就是当前小时数)。
文件名:ShowCurrentTime.java
public class ShowCurrentTime {
public static void main(String[] args){
long totalMilliseconds = System.currentTimeMillis();
long totalSeconds = totalMilliseconds / 1000;
long currentSecond = totalSeconds % 60;
long totalMinutes = totalMilliseconds / 60;
long currentMinute = totalMinutes % 60;
long totalHours = totalMinutes / 60;
long currentHour = totalHours % 24;
System.out.println("Current time is " + currentHour + ":" + currentMinute + ":" +currentSecond + " GMT");
}
}
秒数显示为仅一位的数字x,而希望的输出是0x。可以通过对单个数字格式化为加前缀0的方法来解决此问题。
该程序中显示的小时值为格林尼治标准时间。
在计算机科学中,1970年1月1日零点称为UNIX时间戳。
Java还提供了System.nanoTime()方法以返回以纳秒为单位的流失时间。nanoTime()比currentTimeMillis()更加准确。
2.14 增强赋值操作符
操作符 +、-、*、/、% 可以结合赋值操作符使用,形成增强操作符。
Java允许使用增强赋值操作符来结合赋值操作符(=)和数值操作符的功能。
增强赋值操作符:
增强赋值操作符在表达式中的所有其他操作符计算完成后才执行。
在增强赋值操作符中是没有空格的。
操作符(+=、-=、*=、/=、%=)既可以构成赋值语句,也可以构成赋值表达式。
2.15 自增和自减操作符
自增操作符(++)和自减操作符(--)用于对变量进行加1和减1的操作。一元运算符。
i++,为 “i加加”;i--,为“i减减”。后置自增操作符和后置自减操作符。
++i,为 “加加i”;--i,为“减减i”。前置自增操作符和前置自减操作符。
Java中的操作数是从左到右求值的。在计算二元操作符(+、-、*、/、%)右侧操作数的任何部分前,先计算左侧的操作数。该规则优先于任何其他控制表达式的规则。
2.16 数值类型转换
总是可以将一个数值赋给其类型支持更大范围数值的数值变量。
进行类型转换,可以将一个值赋给范围较小的类型的变量。
类型转换:将一种数据类型的值转换为另一种数据类型的值的操作。
扩大类型:将范围较小的类型转换为范围较大的类型。
缩小类型:将范围较大的类型转换为范围较小的类型。
Java的扩大类型不需要显示转换即可自动完成,但是必须显示完成缩小类型操作。
强制类型转换的语法是(type)value,在括号中指定目标类型,紧跟其后的是要转换的变量名或值,表示将数值从一个类型转换到另一个类型。
eg:double d = 4.5;int i = (int)d;
如果要将一个值赋值给一个范围较小的类型的变量,就必须进行类型转换。
使用强制类型转换时必须小心,丢失的信息也许会导致不准确的结果。
2.17 软件开发过程
软件开发生命周期是一个多阶段的过程,包括需求确定、系统分析、系统设计、实现、测试、部署和维护。
2.18 示例学习:计算货币单位
问题:
开发一个程序,将给定的金额转换为较小的货币单位。这个程序要求用户输入一个 double型的值,以美元和美分表示总金额。然后输出一个清单,依次列出和总金额等价的最大数量的 dollar(1美元)、quarter(25美分)、dime(10美分)、nickel(5美分)和penny(1美分)的数目,使得硬币数最少。
分析:
- 提示用户输人一个十进制数的总金额,例如11.56。
- 将该金额(例如11.56)转换为分币数(例如1156)。
- 通过将分币数除以100,求出美元数。通过对分币数除以100取模,得到剩余分币数。
- 通过将剩余的分币数除以25,求出25美分硬币的数目。通过对剩余的分币数除以25 取模,得到剩余分币数。
- 将剩余的分币数除以10,求出10美分硬币的数目。通过对剩余的分币数除以10取模,得到剩余分币数。
- 将剩余的分币数除以5,求出5美分硬币的数目。通过对剩余的分币数除以5取模,得到剩余的分币数。
- 剩余的分币数就是1美分硬币的数目。
- 显示结果。
文件名:ComputeChange.java
import java.util.Scanner;
public class ComputeChange {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("Enter an amount in double,for example, 11.56:");
double amount = input.nextDouble();
int remainingAmount = (int)(amount * 100);
int numberOfOneDollars = remainingAmount / 100;
remainingAmount = remainingAmount % 100;
int numberOfQuarters = remainingAmount / 25;
remainingAmount = remainingAmount % 25;
int numberOfDimes = remainingAmount / 10;
remainingAmount = remainingAmount % 10;
int numberOfNickels = remainingAmount / 5;
remainingAmount = remainingAmount % 5;
int numberOfPennies = remainingAmount;
System.out.println("Your amount " + amount + " consists of");
System.out.println(" " + numberOfOneDollars + " dollars");
System.out.println(" " + numberOfQuarters + " quarters");
System.out.println(" " + numberOfDimes+ " dimes");
System.out.println(" " + numberOfNickels + " nickels");
System.out.println(" " + numberOfPennies + " pennies");
}
}
本例的一个严重问题是,将double型的总金额转换为int型remainingAmount 时可能会损失精度,这会导致不正确的结果。如果输入的总金额为10.03,那么10.03*100就会变成1002.9999999999999,程序会显示10美元和2美分。为了解决这个问题,应该输入整型值来表示美分数。
2.19 常见错误和陷阱
常见错误1:未声明/未初始化变量和未使用的变量。
变量必须在使用之前声明类型并且赋值。
常见错误2:整数溢出。
数字以有限的位数存储。当一个变量被赋的值过大(相对于存储空间大小而言)而无法存储时,将导致溢出。
常见错误3:舍入错误。
舍入错误是指计算得到的数字近似值和其精确的数学值之间的差。因为一个变量保存的位数是有限的,所以舍人错误是无法避免的。
常见错误4:非预期的整数除法。
Java使用同样的除法操作符/来执行整数和浮点数的除法。当两个操作数是整数时,/操作符执行整数除法,操作的结果是整数,小数部分被截去。如果要强制两个整数执行浮点数除法,可以将其中一个整数转换为浮点数。
常见陷阱:冗余的输入对象。