4.1 引言

  • 本章重点介绍数学函数、字符和字符串对象,并使用它们来开发程序
  • 前面章节介绍了基础编程技术,以及如何使用选择语句编写简单的程序来解决一些基本问题。本章介绍实现常用数学操作的方法。你将在第6章学到如何创建自定义方法
  • 假设你需要估算被四座城市包围的区域的面积,给定这些城市的GPS位置(经纬度),如下图所示。如何编写程序来求解这个问题?在学完本章后,你将可以编写这样的程序。
  • 因为字符串在编程中经常要用到,所以尽早介绍字符串从而开始使用它们来编写使用的程序是有裨益的。本章还给出了字符串对象的简要介绍,你将在第9章和第10章进一步学习对象和字符串的相关知识。

4.2 常用数学函数

  • Java在Math类中提供了许多实用的方法,来计算常用的数学函数。
  • 方法是一组语句,用于执行一个特定的任务。在2.9.4节中我们已经使用过方法pow(a,b)来计算ab ,在3.7节中也使用过random()方法来产生一个随机数。本节介绍Math类中其他的有用方法。这些方法分为三类:
    • 三角函数方法(trigonometric method)
    • 指数函数方法(exponent method)
    • 服务方法(service method)
      • 取整
      • 求最小值
      • 求最大值
      • 求绝对值
      • 随机方法
  • 除了这些方法之外,Math类还提供了两个很有用的double型常量,PI( π )和E(自然对数的底)。可以在任意程序中用Math.PI和Math.E来使用这两个常量

4.2.1 三角函数方法

  • Math类包含表4-1中所示的三角函数方法。
方法 描述
sin(radians) 返回以弧度为单位的角度的三角正弦函数值
cos(radians) 返回以弧度为单位的角度的三角余弦函数值
tan(radians) 返回以弧度为单位的角度的三角正切函数值
toRadians(degree) 将以度为单位的角度值转换为以弧度表示
toDegrees(radians) 将以弧度为单位的角度值转换为以度表示
asin(a) 返回以弧度为单位的角度的反三角正弦函数值
acos(a) 返回以弧度为单位的角度的反三角余弦函数值
atan(a) 返回以弧度为单位的角度的反三角正切函数值
  • sin、cos和tan的参数都是以弧度为单位的角度。asin和atan的返回值是 -π/2 ~ π/2的一个弧度制,acos的返回值在0到π之间。1°相当于π/180弧度,90°相当于π/2弧度,而30°相当于π/6弧度

4.2.2 指数函数方法

  • Math类中有5个与指数函数有关的方法,如表4-2所示
方法 描述
exp(x) 返回e的x次方(ex)
log(x) 返回x的自然对数(lnx = loge x)
log10(x) 返回x的以10为底的对数(log10 x)
pow(a,b) 返回a的b次方(ab)
sqrt(x) 对于x ≥ 0的数字,返回x的平方根(第04章 数学函数、字符和字符串 - 图1

4.2.3 取整方法

  • Math类包括四个取整方法,如表4-3所示
方法 描述
ceil(x) x向上取整为它最接近的整数。该整数作为一个双精度值返回
floor(x) x向下取整为它最接近的整数。该整数作为一个双精度值返回
rint(x) x取整为它最接近的整数。如果x与两个整数的距离相等,偶数的整数作为一个双精度值返回
round(x) 如果x是单精度数,返回(int)Math.floor(x+0.5);如果x是双精度数,返回(long)Math.floor(x+0.5)

4.2.4 min、max和abs方法

4.2.5 random方法

4.2.6 示例学习:计算三角形的角度

  • 给定一个三角形的三边,可以通过以下公式计算角度
  1. A = acos((a * a - b * b - c * c) / (-2 * b * c))
  2. B = acos((b * b - a * a - c * c) / (-2 * a * c))
  3. C = acos((c * c - b * b - a * a) / (-2 * a * b))

程序清单4-1是一个示例程序,提示用户输入三角形三个顶点的x和y坐标值,然后三个角。

程序清单 4-1 ComputeAngles.java

  1. import java.util.Scanner;
  2. public class ComputeAngles {
  3. public static void main(String[] args) {
  4. Scanner input = new Scanner(System.in);
  5. //Prompt the user to enter three points
  6. System.out.print("Enter three points: ");
  7. double x1 = input.nextDouble();double y1 = input.nextDouble();
  8. double x2 = input.nextDouble();double y2 = input.nextDouble();
  9. double x3 = input.nextDouble();double y3 = input.nextDouble();
  10. //Compute three sides
  11. double a = Math.sqrt(Math.pow(x2 - x3, 2) + Math.pow(y2 - y3, 2));
  12. double b = Math.sqrt(Math.pow(x3 - x1, 2) + Math.pow(y3 - y1, 2));
  13. double c = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
  14. //Compute three angle
  15. double A = Math.toDegrees(Math.acos((a * a - b * b - c * c) / (-2 * b * c)));
  16. double B = Math.toDegrees(Math.acos((b * b - a * a - c * c) / (-2 * a * c)));
  17. double C = Math.toDegrees(Math.acos((c * c - b * b - a * a) / (-2 * a * b)));
  18. //Display results
  19. System.out.println("The three angles are: " +
  20. Math.round(A * 100) / 100.0 + " " +
  21. Math.round(B * 100) / 100.0 + " " +
  22. Math.round(C * 100) / 100.0);
  23. }
  24. }
  • 程序提示用户输入三个顶点(第8行)。这个提示消息并不是很清晰,应该给予用户非常清晰的提示,如下所示:
  1. System.out.print("Enter the coordinates of three points separated" + "by spaces like x1 y1 x2 y2 x3 y3: ");
  • 注意,两个点(x1,y1),(x2,y2)之间的距离可以通过公式第04章 数学函数、字符和字符串 - 图2%5E2%20%2B%20(y_2%20-%20y_1)%5E2)#card=math&code=%5Csqrt%28x_2%20-%20x_1%29%5E2%20%2B%20%28y_2%20-%20y_1%29%5E2%29&id=liBNM)计算。程序计算两个点之间的距离,并且应用该公式来计算角度。的角度值保留小数点后两位数字。
  • Math类在程序中使用,但是并没有导入,因为它在java.lang包中。在一个Java程序中,java.lang包中的所有类是隐式导入的。

4.3 字符数据类型和操作

  • 字符数据类型用于表示单个字符
  • 除了处理数值之外,Java还可以处理字符。字符数据类型char用于表示单个字符。字符型字面值用单引号括住。考虑以下代码:

    1. char letter = 'A';
    2. char numChar = '4';


    第一条语句将字符A赋值给char型变量letter。第二条语句将数字字符4赋值给char型变量numChar

  • 字符串字面值必须括在双引号中。而字符字面值是括在单引号中的单个字符。因此,”A”是一个字符串,而’A’是一个字符。

4.3.1 Unicode 和 ASCII码

  • 计算机内部使用二进制数。一个字符在计算机中是以0和1构成的序列的形式来存储的。将字符映射到它的二进制形式的过程称为编码(encoding)。字符有多种不同的编程方式,编码表(encoding scheme)定义该如何编码每个字符。
  • Java支持Unicode码,Unicode码是由Unicode协会建立的一种编码方案,它支持使用世界各种语言所书写的文本的交换、处理和显示。Unicode一开始被设计为16位的字符编码。基本数据类型char试图通过提供一种能够存放任意字符的简单数据类型来利用这个设计。但是。一个16位的编码所能产生的字符只有65536个,它是不足以表示全世界所有字符的。因此Unicode标准被扩展位1 112 064个字符。这些字符都远远超过了原来16位的限制,它们称为补充字符(supplementary character)。Java支持这些补充字符。对补充字符的处理和表示介绍超过了本书的范围。为了简化问题,本书只考虑原来的16位Unicode字符。这些字符都可以存储在一个char型变量中。
  • 一个16位Unicode占两个字节,用以\u开头的4位十六进制数表示,范围从'\u0000''\uFFFF'。关于十六进制数字的更多内容请参见附录F。例如:welcome被翻译成中文需要两个字符”欢迎“。这两个字符的Unicode为\u6B22\u8FCE。希腊字母 α β γ 的Unicode是\u03b1\u03b2\u03b3
  • 大多数计算机采用ASCII(美国标准信息交换码: American Standard Code for Information Interchange ),它是表示所有大小写字母、数字、标点符号和控制字符的8位编码表。Unicode码包括ASCII码,从'\u0000''\u007F'对应128个ASCII字符。表4-4给出了一些常用字符的ASCII码。附录B给出了ASCII字符的完整清单,以及它们的十进制和十六进制编码。
字符 十进制编码值 Unicode值
‘0’ ~ ‘9’ 48 ~ 57 \u0030 ~ \u0039
‘A’ ~ ‘Z’ 65 ~ 90 \u0041 ~ \u005A
‘a’ ~ ‘z’ 97 ~ 122 \u0061 ~ \u007A
  • Java程序中,可以使用像’X’、’1’和’$’这样的ASCII字符,也可以使用Unicode码。例如,下面的语句是等价的:
    1. char letter = 'A';
    2. char letter = '\u0041'; // Character A's Unicode is 0041
  • 两条语句都将字符A赋值给char型变量letter。
  • 自增和自减操作符也可用在char型变量上,这会得到该字符之前或之后的Unicode字符。例如,下面的语句显示字符b。
    1. char ch = 'a';
    2. System.out.println(++ch);

4.3.2 特殊字符的转义序列

  • 假如你想在输出时显示如下带引号的信息,你能编写如下所示的这条语句吗?
    1. System.out.println("He said "Java is fun"");
  • 答案是不能,这条语句有语法错误。编译器会认为第二个引号字符就是这个字符串的结束标志,从而不知道该如何处理剩余的字符。
  • 为了解决这个问题,Java定义了一种特殊的标记来表示特殊字符,如表4-5所示。这种标记称为转义序列,转义序列由反斜杠(\)后面加上一个字符或者一些数字位组成,比如,\t是一个表示Tab字符的转义符,而诸如\03b1的转义符用于表示一个Unicode。转义序列中的符号作为一个整体翻译,而不是分开翻译。一个转义序列被当作一个字符。
  • 所以,现在我们可以使用下面的语句输出带引号的消息:
    1. System.out.println("He said \"Java is fun\"");
  • 它的输出是:
    1. He said "Java is fun"

    注意,符号\和””一起代表一个字符
转义序列 名称 Unicode码 十进制值
\b 退格键 \u0008 8
\t Tab键 \u0009 9
\n 换行符 \u000A 10
\f 换页符 \u000C 12
\r 回车符 \u000D 13
\ 反斜杠 \u005C 92
\“ 双引号 \u0022 34
  • 反斜杠\被称为转义字符。它是一个特殊字符。要显示这个字符,需要使用转义序列\\。比如,下面的代码
    1. System.out.println("\\t is a tab character");

    显示

4.3.3 字符型数据与数值型数据之间的转换

  • char型数据可以转换成任意一种数值类型,反之亦然。将整数转换成char型数据时,只用到该数据的低十六位,其余部分都被忽略。例如:
  1. //Note a hex integer is written using prefix OX
  2. char ch = (char)0XAB0041; //The lower 16 bits hex code 0041 is assigned to ch
  3. System.out.println(ch); //ch is character A
  • 要将一个浮点值转换成char型时,首先将浮点值转换成int型,然后将这个整型值转换位char型。
  1. char ch = (char)65.25; //Decimal 65 is assigned to ch
  2. System.out.println(ch); //ch is character A
  • 当一个char型数据转换成数值型时,这个字符的Unicode就被转换成某个指定的数值类型。
  1. int i = (int)'A'; //The Unicode of character A is assigned to i
  2. System.out.println(i); //i is 65
  • 如果转换结果适用于目标变量,就可以使用隐式转换方式;否则,必须使用显式转换方式。例如,因为’a’的Unicode是97,它在一个字节的范围内,所以以下赋值就可以使用隐式转换方式
    1. byte b = 'a';
    2. int i = 'a';
  • 但是,因为Unicode码\uFFF4超过了一个字节的范围,所以下面的转换就是不正确的:
    1. byte b = '\uFFF4';
  • 为了强制赋值,就必须使用显式转换,如下所示
    1. byte b = (byte)'\uFFF4';
  • 0 ~ FFFF 的任何一个十六进制正整数都可以隐式地转换成字符型数据。而不在此范围内的任何其他数值都必须显式地转换为char型
  • 所有数值操作符都可以用在char型操作数上。如果另一个操作数是一个数字或字符,那么char型操作数就会被自动转换成一个数字。如果另一个操作数是一个字符串,字符就会与该字符串相连。例如,下面的语句:
    1. int i = '2' + '3'; //(int)'2' is 50 and (int)'3' is 51
    2. System.out.println("i is " + i); //i is 101
    3. int j = 2 + 'a'; //(int)'a' is 97
    4. System.out.println("j is " + j); //j is 99
    5. System.out.println(j + "is the Unicode for character " + (char)j);
    6. //99 is the Unicode for character c
    7. System.out.println("Chapter " + '2');
  • 显示结果
    1. i is 101
    2. j is 99
    3. 99 is the Unicode for character c
    4. Chapter 2

4.3.4 字符的比较和测试

  • 两个字符可以使用关系操作符进行比较,如同比较两个数字一样。这是通过比较两个字符的Unicode值实现的。比如:
  • ‘a’ < ‘b’为true,因为’a’(97)的Unicode值比’b’(98)的Unicode值小
  • 程序中经常需要测试一个字符的数字、字母;大写字母,还是小写字母。如附录B的ASCII字符集所示,小写字母的Unicode是连续的整数,从’a’的Unicode开始,然后是’b’、’c’、….,’z’。同理,对于大写字母和数字字符也是这样。这个特征可以用于编写测试字符的编码。比如下列代码测试字符ch是大写字母、小写字母还是数字字符。
    1. if (ch >= 'A' && ch <= 'Z')
    2. System.out.println(ch + " is an uppercase letter");
    3. else if (ch >= 'a' && ch <= 'z')
    4. System.out.println(ch + " is a lowercase letter");
    5. else if (ch >= '0' && ch <= '9')
    6. System.out.println(ch + " is a numeric character");
方法 描述
isDigit(ch) 如果指定的字符是一个数字,返回true
isLetter(ch) 如果指定的字符是一个字母,返回true
isLetterOrDigit(ch) 如果指定的字符是一个字母或者数字,返回true
isLowerCase(ch) 如果指定的字符是一个小写字母,返回true
isUpperCase(ch) 如果指定的字符是一个大写字母,返回true
toLowerCase(ch) 返回指定的字符的小写形式
toUpperCase(ch) 返回指定的字符的大写形式

4.4 String类型

  • 字符串是一个字符序列
方法 描述
length() 返回字符串中的字符数
charAt(index) 返回字符串中指定位置的字符
concat(s1) 将本字符串和字符串s1连接,返回一个新字符串
toUpperCase() 返回一个新字符串,其中所有的字母大写
toLowerCase() 返回一个新字符串,其中所有的字母小写
trim() 返回一个新字符串,去掉了两边的空白字符
  • String是Java中的对象。表4-7中的方法只能从一个特定的字符串实例来调用。由于这个原因,这些方法称为实例方法。非实例方法称为静态方法。静态方法可以不使用对象来调用。定义在Math类中的所有方法都是静态方法。它们没有绑定到一个特定的对象实例上。调用一个实例方法的语法是reference - Variable.methodName(arguments)。一个方法可以由多个参数,或者没有参数。例如,charAt(index)方法具有一个参数,但是length()方法则没有参数。回顾曾经介绍过的,调用静态方法的语法是ClassName.methodName(arguments)。例如,Math类中的pow方法可以使用Math.pow(2,2.5)来调用

4.4.1 获取字符串长度

  • 可以调用字符串的length()方法获取它的长度。例如下面的代码
    1. String message = "Welcome to Java";
    2. System.out.println("The length of " + message + " is " + message.length());
  • 显示
    1. The length of Welcome to Java is 15
  • 使用一个字符串时,往往是知道它的字面值的。为方便起见,Java允许在不创建新变量的情况下,使用字符串字面值直接引用字符串。这样,”Welcome to Java”.length()是正确的,它返回15。注意,””表示空字符串,并且””.length()为0.

4.4.2 从字符串中获取字符

  • 在字符串s中越界访问字符是一种常见的程序设计错误。为了避免此类错误,要确保使用的下标不会超过s.length() -1 。例如,s.charAt(s.length())会造成一个StringIndexOutOfBoundsException异常。

4.4.3 连接字符串

4.4.4 字符串转换

4.4.5 从控制台读取字符串

  • next()方法读取以空白字符结束的字符串(即’’、’\t’、’\f’、’\r’或’\n’)可以使用nextLine()方法读取一整行文本。nextLine()方法读取以按下回车键为结束标志的字符串。例如,下面的语句读取一行文本
    1. Scanner input = new Scanner(System.in);
    2. System.out.println("Enter a line: ");
    3. String s = input.nextLine();
    4. System.out.println("The line entered is " + s);
  • 为了方便,将使用方法next()、nextByte()、nextShort()、nextInt()、nextLong()、nextFloat()和nextDouble()的输入称为基于标记的输入,因为它们读取采用空白字符分隔的单个元素,而不是读取整行。nextLine()方法称为基于行的输入。
  • 为了避免输入错误,程序中不要在基于标记的输入之后使用基于行的输入,原因将在12.11.4节中解释

4.4.6 从控制台读取字符

4.4.7 字符串比较

  • String类提供了如表4-8所示的方法,用于比较两个字符串。
方法 描述
equals(s1) 如果该字符串等于字符串s1,返回true
equalsIgnoreCase(s1) 如果该字符串等于字符串s1,返回true,不区分大小写
compareTo(s1) 返回一个大于0、等于0、小于0的整数,表明该字符串是否大于、等于或者小于s1
compareToIgnoreCase(s1) 和compareTo一样,除了比较是不区分大小写的外
startsWith(suffix) 如果字符串以特定的前缀开始,返回true
endWith(suffix) 如果字符串以特定的后缀结束,返回true
contains(s1) 如果s1是该字符串的子字符串,返回true
  • 如果使用像>、≥、<或≤这样的比较操作符比较两个字符串,就会发生语法错误。替代的方法就是使用s1.compareTo(s2)来进行比较
  • 如果两个字符串相等,equals方法返回true;如果它们不等,方法返回false。compareTo方法会根据一个字符串是否等于、大于或小于另一个字符串,分别返回0、正整数或负整数。

程序清单 4-2 OrdeTwoCities.java

  1. import java.util.Scanner;
  2. public class OrdeTwoCities {
  3. public static void main(String[] args) {
  4. Scanner input = new Scanner(System.in);
  5. //Prompt the user to enter two cities
  6. System.out.print("Enter the first city: ");
  7. String city1 = input.nextLine();
  8. System.out.print("Enter the second city");
  9. String city2 = input.nextLine();
  10. if (city1.compareTo(city2) < 0) {
  11. System.out.println("The cities in alphabetical order are " +
  12. city1 + " " + city2);
  13. } else {
  14. System.out.println("The cities in alphabetical order are " +
  15. city2 + " " + city1);
  16. }
  17. }
  18. }

4.4.8 获得子字符串

方法 描述
substring(beginIndex) 返回该字符串的子串,从指定位置beginIndex的字符开始到字符串的结尾,如图4-2所示
substring(beginIndex, endIndex) 返回该字符串的子串,从指定位置beginIndex的字符开始到下标为endIndex -1 的字符,如图4-2所示。注意,位于endIndex位置的字符不属于该子字符串的一部分
  • 如果beginIndex为endIndex,substring(beginIndex, endIndex)返回一个长度为0的空字符串。如果beginIndex > endIndex,将发生运行时错误。

4.4.9 获取字符串中的字符或者子串

  • String类提供了几个版本的indexOf和lastIndexOf方法,它们可以在字符串中找出一个字符或一个子串,如表4-10所示
方法 描述
indexOf(ch) 返回字符串中出现的第一个ch的下标。如果没有匹配的,返回-1
indexOf(ch,fromIndex) 返回字符串中fromIndex之后出现的第一个ch的下标。如果没有匹配的,返回-1
indexOf(s) 返回字符串中出现的第一个字符串s的下标。如果没有匹配的,返回-1
indexOf(s, fromIndex) 返回字符串中fromIndex之后出现的第一个字符串s的下标。如果没有匹配的,返回-1
lastIndexOf(ch) 返回字符串中出现的最后一个ch的下标。如果没有匹配的,返回-1
lastIndexOf(ch,fromIndex) 返回字符串中fromIndex之前出现的最后一个ch的下标。如果没有匹配的,返回-1
lastIndexOf(s) 返回字符串中出现的最后一个字符串s的下标。如果没有匹配的,返回-1
lastIndexOf(s,fromIndex) 返回字符串中fromIndex之前出现的最后一个字符串s的下标。如果没有匹配的,返回-1

4.4.10 字符串和数字间的转换

4.5 示例学习

4.5.1 猜测生日

程序清单 4-3 GuessBirthday.java

  1. import java.util.Scanner;
  2. public class GuessBirthday {
  3. public static void main(String[] args) {
  4. String set1 = " 1 3 5 7\n" +
  5. " 9 11 13 15\n" +
  6. "17 19 21 23\n" +
  7. "25 27 29 31";
  8. String set2 = " 2 3 6 7\n" +
  9. "10 11 14 15\n" +
  10. "18 19 22 23\n" +
  11. "26 27 30 31";
  12. String set3 = " 4 5 6 7\n" +
  13. "12 13 14 15\n" +
  14. "20 21 22 23\n" +
  15. "28 29 30 31";
  16. String set4 = " 8 9 10 11\n" +
  17. "12 13 14 15\n" +
  18. "24 25 26 27\n" +
  19. "28 29 30 31";
  20. String set5 = "16 17 18 19\n" +
  21. "20 21 22 23\n" +
  22. "24 25 26 27\n" +
  23. "28 29 30 31";
  24. int day = 0;
  25. //Create a Scanner
  26. Scanner input = new Scanner(System.in);
  27. //Prompt the user to answer questions
  28. System.out.print("\nIs your birthday in Set1?\n");
  29. System.out.print(set1);
  30. System.out.print("\nEnter 0 for No and 1 for Yes: ");
  31. int answer = input.nextInt();
  32. if (answer == 1){
  33. day += 1;
  34. }
  35. //Prompt the user to answer questions
  36. System.out.print("\nIs your birthday in Set2?\n");
  37. System.out.print(set2);
  38. System.out.print("\nEnter 0 for No and 1 for Yes: ");
  39. answer = input.nextInt();
  40. if (answer == 1) {
  41. day += 2;
  42. }
  43. //Prompt the user to answer questions
  44. System.out.print("\nIs your birthday in Set3?\n");
  45. System.out.print(set3);
  46. System.out.print("\nEnter 0 for No and 1 for Yes: ");
  47. answer = input.nextInt();
  48. if (answer == 1) {
  49. day += 4;
  50. }
  51. //Prompt the user to answer questions
  52. System.out.print("\nIs your birthday in Set4?\n");
  53. System.out.print(set4);
  54. System.out.print("\nEnter 0 for No and 1 for Yes: ");
  55. answer = input.nextInt();
  56. if (answer == 1) {
  57. day += 8;
  58. }
  59. //Prompt the user to answer questions
  60. System.out.print("\nIs your birthday in Set5?\n");
  61. System.out.print(set5);
  62. System.out.print("\nEnter 0 for No and 1 for Yes: ");
  63. answer = input.nextInt();
  64. if (answer == 1) {
  65. day += 16;
  66. }
  67. System.out.println("\nYour birthday is " + day + "!");
  68. }
  69. }

4.5.2 将十六进制数转换为十进制数

程序清单 4-4 HexDigit2Dec.java

  1. import java.util.Scanner;
  2. public class HexDigit2Dec {
  3. public static void main(String[] args) {
  4. Scanner input = new Scanner(System.in);
  5. System.out.print("Enter a hex digit: ");
  6. String hexString = input.nextLine();
  7. //Check if the hex string has exactly one character
  8. if (hexString.length() != 1) {
  9. System.out.println("You must enter exactly one character");
  10. System.exit(1);
  11. }
  12. //Display decimal value for the hex digit
  13. char ch = Character.toUpperCase(hexString.charAt(0));
  14. if ('A' <= ch && ch <= 'F') {
  15. int value = ch - 'A' + 10;
  16. System.out.println("The decimal value for hex digit " +
  17. ch + " is " + value);
  18. } else if (Character.isDigit(ch)) {
  19. System.out.println("The decimal value for hex digit " +
  20. ch + " is " + ch);
  21. } else {
  22. System.out.println(ch + " is an invalid input");
  23. }
  24. }
  25. }

4.5.3 使用字符串修改彩票程序

程序清单 4-5 LotteryUsingStrings.java

  1. import java.util.Scanner;
  2. public class LotteryUsingStrings {
  3. public static void main(String[] args) {
  4. //Generate a lottery as a two-digit string
  5. String lottery = "" + (int) (Math.random() * 10)
  6. + (int) (Math.random() * 10);
  7. //Prompt the user to enter a guess
  8. Scanner input = new Scanner(System.in);
  9. System.out.print("Enter your lottery pick(two digits");
  10. String guess = input.nextLine();
  11. //Get digits from lottery
  12. char lotteryDigit1 = lottery.charAt(0);
  13. char lotteryDigit2 = lottery.charAt(0);
  14. //Get digits from guess
  15. char guessDigit1 = guess.charAt(0);
  16. char guessDigit2 = guess.charAt(1);
  17. System.out.println("The lottery number is " + lottery);
  18. //Check the guess
  19. if (guess.equals(lottery)) {
  20. System.out.println("Exact match: you win $10,000");
  21. } else if (guessDigit2 == lotteryDigit1 && guessDigit1 == lotteryDigit2) {
  22. System.out.println("Match all digits: you win $3,000");
  23. } else if (guessDigit1 == lotteryDigit1 || guessDigit1 == lotteryDigit2
  24. || guessDigit2 == lotteryDigit1 || guessDigit2 == lotteryDigit2) {
  25. System.out.println("Match one digit: you win $1,000");
  26. } else {
  27. System.out.println("Sorry, no match");
  28. }
  29. }
  30. }

4.6 格式化控制台输出

  • 可以使用System.out.printf方法在控制台上显示格式化输出。
  • 格式限定符指定每项应该如何显示。这里的项可以是数值、字符、布尔值或字符串。简单的格式标识符是以百分号(%)开头的转换码。表4-11列出了一些常用的简单格式限定符
限定符 输出 举例 限定符 输出 举例
%b 布尔值 true或false %f 浮点数 45.460000
%c 字符 ‘a’ %e 标准科学记数法形式的数 4.556 000e+01
%d 十进制整数 200 %s 字符串 “Java is cool”
举例 输出
%5c 输出字符并在这个字符条目前面加4个空格
%6b 输出布尔值,在false值前加一个空格,在true值前加两个空格
%5d 输出整数项,宽度至少为5。如果该条目的数字位数小于5,就在数字前面加空格。如果该条目的位数大于5,则自动增加宽度
%10.2f 输出的浮点数项的宽度至少为10,包括小数点和小数点后两位数字。这样,给小数点前分配了7位数字。如果该条目小数点前的位数小于7,就在数字前面加空格。如果该条目小数点前的位数大于7,则自动增加宽度
%10.2e 输出的浮点数项的宽度至少为10,包括小数点、小数点后两位数字和指数部分。如果按科学记数法显示的数字位数小于10,就在数前加空格
%12s 输出的字符串宽度至少为12个字符。如果该字符串条目小于12个字符。就在该字符串前加空格。如果该字符串条目多于12个字符,则自动增加宽度
  • 条目与格式标识符必须在类型上严格匹配。对应于格式标识符%f或%e的条目必须是浮点型值,例如: 是40.0而不能是40。因此,int型变量不能匹配%f或%e。可以使用%.2f来指定一个小数点后两位的浮点数值,而使用%0.2f是不正确的。
  • 使用符号%来标记格式限定符,要在格式字符串里输出字面值%,需要使用%%,例如,以下代码
    1. System.out.printf("%.2f%%\n",75.234);
  • 显示
    1. 75.23%
  • 程序清单4-6 给出一个使用printf来显示一个表格的程序。

程序清单 4-6 FormatDemo.java

  1. public class FormatDemo {
  2. public static void main(String[] args) {
  3. //Display the header of the table
  4. System.out.printf("%-10s%-10s%-10s%-10s%-10s\n", "Degrees", "Radians", "Sine", "Cosine", "Tangent");
  5. //Display values for 30 degrees
  6. int degrees = 30;
  7. double radians = Math.toRadians(degrees);
  8. System.out.printf("%-10d%-10.4f%-10.4f%-10.4f%-10.4f\n",
  9. degrees, radians, Math.sin(radians), Math.cos(radians), Math.tan(radians));
  10. }
  11. }