《写给大忙人看的 Java 核心技术》 01 章练习
1.写个程序,它读取一个整数并以二进制、八进制和十六进制输出。以十六进制浮点数输出倒数。
参考答案:
package com.example;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Scanner;
public class LearnJava {
public static void main(String[] args) {
System.out.print("Please enter an Integer: ");
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextInt()) {
Integer number = scanner.nextInt();
System.out.println("Binary output: " + Integer.toString(number, 2));
// method 0
System.out.println("Octal output: 0" + Integer.toString(number, 8));
System.out.println("Hexadecimal output: 0x"
+ Integer.toString(number, 16).toUpperCase());
// method 1
System.out.printf("Octal output: 0%o\n", number);
System.out.printf("Hexadecimal output: 0x%X\n", number);
// method 0
BigDecimal bigDecimal = new BigDecimal("1.0").divide( new BigDecimal(number),
MathContext.DECIMAL64);
System.out.println(bigDecimal);
System.out.printf("Hexadecimal Inverse output: %A\n", bigDecimal.doubleValue());
// method 1
System.out.println(1.0/number);
System.out.printf("Hexadecimal Inverse output: %A\n", 1.0/number);
}
}
}
其中 “1.0/number” 的值依赖于编译器,也就是说这个值是平台相关的,而 “BigDecimal("1.0").divide( new BigDecimal(number), MathContext.DECIMAL64);” 的值,则依赖于上述代码中 “MathContext.DECIMAL64” 对应的这个参数的取值,也就是平台无关的。在上述代码中,它们的值之所以是相同的,是因为 toby 的电脑系统是 64 位的 Ubuntu 系统。
01题输出效果:
01题输出效果2.写个程序,它读取整数,然后经过模运算转换为 0° ~ 359° 之间的值。首先以操作符 % 完成,然后再试 floorMod。
参考答案:
package com.example;
import java.util.Scanner;
public class LearnJava {
public static void main(String[] args) {
System.out.println("Please enter a radian: ");
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextInt()) {
Integer number = scanner.nextInt();
// method 0
System.out.println("The effective radian value is: " + (number % 360));
// method 1
System.out.println("The effective radian value is: " + Math.floorMod(number, 360));
System.out.println("Please enter a radian: ");
}
}
}
02题输出效果:
02题输出效果
03.只用条件操作符,写一个程序,读取三个整数并输出最大的。使用 Math.max 实现同样的功能。
参考答案:
package com.example;
import java.util.Scanner;
public class LearnJava {
public static void main(String[] args) {
System.out.print("Please enter first Integer: ");
Scanner scanner = new Scanner(System.in);
boolean enterDataOk = false;
if (scanner.hasNextInt()) {
Integer number0 = scanner.nextInt();
System.out.print("Please enter second Integer: ");
if (scanner.hasNextInt()) {
Integer number1 = scanner.nextInt();
System.out.print("Please enter third Integer: ");
if (scanner.hasNextInt()) {
enterDataOk = true;
Integer number2 = scanner.nextInt();
// method 0
int result = number0 > number1 ? number0 : number1;
result = result > number2 ? result : number2;
System.out.println("The max value is: " + result);
// method 1
System.out.println("The max value is: "
+ Math.max(Math.max(number0, number1), number2));
}
}
}
if (!enterDataOk) {
System.out.print("Input data failed!");
}
}
}
03题输出结果:
03题输出结果04.写个程序,输出 double 类型中的最小正数值和最大正数值。提示:在 Java API 文档中查询 Math.nextUp
参考答案:
package com.example;
public class LearnJava {
public static void main(String[] args) {
System.out.println("The max positive number: "
+ Math.nextDown(Double.POSITIVE_INFINITY));
System.out.println("The min positive number: " + Math.nextUp(0));
}
}
04题输出结果:
04题输出结果05.当你将一个 double 类型的值转换为 int 类型的值,并且该值大于最大可能的 int 值时,会发生什么?试试看。
参考答案:
package com.example;
public class LearnJava {
public static void main(String[] args) {
double normalDouble = 123456.789D;
System.out.println("The normal double number: " + normalDouble);
int normalValue = (int) normalDouble;
System.out.println("The int value of the normal double number: " + normalValue);
double maxDouble = Math.nextDown(Double.POSITIVE_INFINITY);
System.out.println("The max positive number: " + maxDouble);
int intValue = (int) maxDouble;
System.out.println("The int value of the max positive number: " + intValue);
}
}
05题输出结果:
05题输出结果由输出可见,如果 Double 类型的数据较大的话,强制转换将数据截短了,只保留了 Integer 类型能够表示的最大数值。关于 “2147483647” ,它是 2147483646 与 2147483648 之间的自然数,也是欧拉在 1772 年所发现的一个梅森素数,它等于 2^31-1,是 32 位操作系统中最大的符号型整型常量。
06.写个程序,计算阶乘 n! = 1 × 2 × ... × n,使用 BigInteger。计算 1000 的阶乘。
参考答案:
package com.example;
import java.math.BigInteger;
public class LearnJava {
private static BigInteger factorial(BigInteger value) {
BigInteger bigInteger = value.subtract(BigInteger.ONE);
if (bigInteger.compareTo(BigInteger.ONE) > 0) {
return value.multiply(factorial(bigInteger));
}
return value.multiply(bigInteger);
}
public static void main(String[] args) {
System.out.println("The factorial of 1000 is: "
+ factorial(BigInteger.valueOf(1000)));
}
}
06题输出结果:
06题输出结果答案长的有些不像话,上图其实没有显示全,完整的答案是这样的:
The factorial of 1000 is: 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
足足有 2568 位:
2568 位这也可以看出 BigInteger 的强大之处。
07.写个程序,读取 0~65535 之间的两个数,在 short 变量中存储,并计算它们的无符号之和、之差、之积、之商和余数,不要将它们转换为 int 类型。
参考答案:
package com.example;
import java.util.Scanner;
public class LearnJava {
private static int toUnsigned(short value) {
return value & 0xFFFF;
}
public static void main(String[] args) {
System.out.print("Please enter first Short(0~65535): ");
Scanner scanner = new Scanner(System.in);
boolean enterDataOk = false;
if (scanner.hasNextInt()) {
short number0 = (short)scanner.nextInt();
System.out.print("Please enter second Short(0~65535): ");
if (scanner.hasNextInt()) {
enterDataOk = true;
short number1 = (short) scanner.nextInt();
System.out.println(toUnsigned(number0) + " + " + toUnsigned(number1)
+ " = " + (toUnsigned(number0) + toUnsigned(number1)));
System.out.println(toUnsigned(number0) + " - " + toUnsigned(number1)
+ " = " + (toUnsigned(number0) - toUnsigned(number1)));
System.out.println(toUnsigned(number0) + " * " + toUnsigned(number1)
+ " = " + (toUnsigned(number0) * toUnsigned(number1)));
System.out.println(toUnsigned(number0) + " / " + toUnsigned(number1)
+ " = " + (toUnsigned(number0) / toUnsigned(number1)));
}
}
if (!enterDataOk) {
System.out.print("Input data failed!");
}
}
}
07题输出结果:
07题输出结果08.写个程序,读取一个字符串并输出该字符串所有的非空子字符串。
参考答案:
package com.example;
public class LearnJava {
public static void main(String[] args) {
String testStr = "Please enter\n first\t Short (0~65535): ";
String[] testStrArray = testStr.split("\\s+");
for (String t : testStrArray) {
System.out.println("Child String: " + t);
}
}
}
08题输出结果:
08题输出结果09.“1.5.3” 节中有个例子,两个字符串 s 和 t,虽然 s.equals(t) 为真,但是 s != t 。找出不使用 substring 方法的不同例子。
参考答案:
package com.example;
public class LearnJava {
public static void main(String[] args) {
String testStr = "Please enter\n first\t Short (0~65535): ";
String[] testStrArray = testStr.split("\\s+");
for (String t : testStrArray) {
System.out.println("Child String: " + t);
}
System.out.println("testStrArray[0] == \"Please\" result: "
+ (testStrArray[0] == "Please") );
System.out.println("testStrArray[0].equals(\"Please\") result: "
+ testStrArray[0].equals("Please") );
}
}
09题输出结果:
09题输出结果10.写个程序,先产生随机的 long 型整数,然后模 36,最后输出由字母和数字组成的随机字符串。
参考答案:
package com.example;
import java.util.Random;
public class LearnJava {
public static void main(String[] args) {
Random random = new Random();
random.setSeed(System.currentTimeMillis());
String chars = "abcdefghijklmnopqrstuvwxyz0123456789";
String outputStr = "";
for (int i=0; i<36; ++i) {
int index = Math.abs((int)(random.nextLong()%36));
outputStr += chars.charAt(index);
}
System.out.println("outputStr: " + outputStr);
}
}
10题输出结果:
10题输出结果11.写个程序,读取一行文本并输出所有非 ASCII 字符,以及它们的 Unicode 值。
参考答案:
package com.example;
public class LearnJava {
private static String toUnicodeExcludeAscii(String str) {
StringBuilder retStr = new StringBuilder();
for(int i=0; i<str.length(); i++) {
int cp = Character.codePointAt(str, i);
int charCount = Character.charCount(cp);
if (charCount > 1) {
i += charCount - 1; // 一些 unicode 字符跨越两个 Java 字符。
if (i >= str.length()) {
throw new IllegalArgumentException("truncated unexpectedly");
}
}
if (cp > 128) {
retStr.append(String.format("\\u%x", cp));
}
}
return retStr.toString();
}
private static String unicodeToNormal(String str) {
StringBuilder retStr = new StringBuilder();
String[] unicodeArray = str.split("\\\\u");
for (String aChar : unicodeArray) {
if (aChar.isEmpty()) {
continue; // 第一个 aChar 为空
}
int data = Integer.parseInt(aChar, 16);
retStr.append((char) data);
}
return retStr.toString();
}
public static void main(String[] args) {
String testStr0 = "ASCII(American Standard Code for Information Interchange,\n" +
"美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和\n" +
"其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO/IEC 646。\n";
String testStr1 = toUnicodeExcludeAscii(testStr0);
System.out.println("toUnicodeExcludeAscii: " + testStr1);
System.out.println("unicodeToNormal: " + unicodeToNormal(testStr1));
}
}
11题输出结果:
11题输出结果注意:本题中我们要考虑到一些 unicode 字符跨越两个 Java 字符的问题。
12.JDK(Java 开发工具箱)包含一个 src.zip 文件,该文件有 Java 库的源代码。解压该文件,用你喜欢的文本搜索工具,找到带标签的 break 和 continue 的用法。选择其中一个并使用不带标签的声明重写。
参考答案:
package com.example;
public class LearnJava {
private static void testBreakWithTag(){
int i = 0;
outer:
while (true)
{
System.out.print("Pass "+(i++)+":");
for(int j=0; j<100; j++)
{
if(j==10)
break outer;
System.out.print(j+" ");
}
// 如果带标签,那么下面的两行代码不会被执行
System.out.println();
System.out.println("HA HA HA HA ...");
}
System.out.println("loops complete.");
}
private static void testBreakNoTag(){
int i=0;
int j=0;
while (j<10) {
System.out.print("Pass "+(i++)+":");
for(; j<100; j++)
{
if(j==10)
break;
System.out.print(j+" ");
}
System.out.println();
System.out.println("HA HA HA HA ...");
}
System.out.println("loops complete.");
}
private static void testContinueWithTag(){
int i=0;
int j=0;
outer:
while (j<10)
{
System.out.print("Pass "+(i++)+":");
for(; j<100; j++)
{
if(j==10)
continue outer;
System.out.print(j+" ");
}
// 如果带标签,那么下面的两行代码不会被执行
System.out.println();
System.out.println("HA HA HA HA ...");
}
System.out.println("loops complete.");
}
private static void testContinueNoTag(){
System.out.print("Pass "+0+":");
for(int j=0; j<10; j++)
{
System.out.print(j+" ");
}
System.out.println("loops complete.");
}
public static void main(String[] args) {
testBreakWithTag();
testBreakNoTag();
testContinueWithTag();
testContinueNoTag();
}
}
12题输出结果:
12题输出结果这个是自己写的示例,可能不是很合理,也欢迎大家补充。
13.写个程序,可以输出一组彩票组合,该组合由 1~49 之间的 6 个不同数字组成。为产生 6 个不同数字,先用 1~ 49 填充一个数组。然后随机选择一个索引并删除对应元素,重复 6 次,并输出排序后的结果。
参考答案:
package com.example;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class LearnJava {
public static void main(String[] args) {
List<Integer> integers = new ArrayList<>();
for (int i=1; i<50; ++i) {
integers.add(i);
}
Random random = new Random();
random.setSeed(System.currentTimeMillis());
StringBuilder stringBuilder = new StringBuilder();
for (int i=0; i<6; ++i){
stringBuilder.append(integers.remove(random.nextInt(integers.size() - 1)));
if (i < 5) {
stringBuilder.append(" ");
}
}
System.out.println("The result is: " + stringBuilder.toString());
}
}
13题输出结果:
13题输出结果14.写个程序,读取整型的二维数组并判断它是否是魔方(也就是,所有的行之和、列之和,以及对角线之和都是相同的)。接受可以分隔成单个整数的行输入,当用户输入空白行时停止。例如,如下输入
16 3 2 13
3 10 11 8
9 6 7 12
4 15 14 1
(空白行)
程序应该确认用户输入的数组是否为魔方。
参考答案:
package com.example;
import java.util.ArrayList;
import java.util.Scanner;
public class LearnJava {
public static void main(String[] args) {
System.out.println("Please enter first numbers Line: ");
Scanner scanner = new Scanner(System.in);
ArrayList<Long> rowSums = new ArrayList<>();
ArrayList<Long> columnSums = new ArrayList<>();
Long leftTopToRightBottomSum = 0L;
Long rightTopToLeftBottomSum = 0L;
boolean enterDataOk = false;
int columnCount = -1;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
String[] numbers = line.split(" ");
if (numbers.length <= 1) {
break; // 无输入或者只输入一个数字时,直接退出
}
if (-1 == columnCount) {
columnCount = numbers.length;
} else {
if (columnCount != numbers.length) {
break; // 新输入的行的数字个数少于或者
// 多于第一行数字的个数时,直接退出
}
}
long rowSum = 0;
for (int i=0; i<columnCount; ++i) {
Long numberValue = Long.valueOf(numbers[i]);
Long columnSum = (columnSums.size() <= i ? 0L : columnSums.get(i));
if (columnSums.size() <= i) {
columnSums.add(columnSum + numberValue);
} else {
columnSums.set(i, columnSum + numberValue);
}
rowSum += numberValue;
}
leftTopToRightBottomSum += Long.valueOf(numbers[rowSums.size()]);
rightTopToLeftBottomSum += Long.valueOf(
numbers[columnCount - rowSums.size() - 1]);
rowSums.add(rowSum);
if (rowSums.get(0) != rowSum) {
break; // 出现新的行的和与第一行的和不相同时,直接退出
}
if (rowSums.size() == columnCount) {
Long allSums = 0L;
for (Long columnSum : columnSums) {
allSums += columnSum;
}
enterDataOk = (allSums/columnCount == rowSums.get(0))
&& leftTopToRightBottomSum.equals(rightTopToLeftBottomSum);
break; // 行数与列数相同达到魔方要求,直接退出
}
}
if (!enterDataOk) {
System.out.println("this is not a Rubik's cube!");
} else {
System.out.println("this is a Rubik's cube, Congratulations!");
}
}
}
14题输出结果:
14题输出结果15.写个程序,在 ArrayList<ArrayList<Integer>> 中存储给定 n 的帕斯卡三角形。
什么是帕斯卡(也叫杨辉)三角形?从下面的动态图片就很简单明了地知道了:
1416275138275.gif参考答案:
package com.example;
import java.util.ArrayList;
import java.util.Scanner;
public class LearnJava {
public static void main(String[] args) {
System.out.println("Please enter an Integer:");
Scanner scanner = new Scanner(System.in);
ArrayList<ArrayList<Integer>> pascalTriangle = new ArrayList<>();
if (scanner.hasNextInt()) {
Integer n = scanner.nextInt();
if (n >= 1) {
ArrayList<Integer> data = new ArrayList<>();
data.add(1);
pascalTriangle.add(data);
}
if (n >= 2) {
ArrayList<Integer> data = new ArrayList<>();
data.add(1);
data.add(1);
pascalTriangle.add(data);
}
for (int i = 3; i <=n; i++) {
ArrayList<Integer> data = new ArrayList<>();
ArrayList<Integer> prev = pascalTriangle.get(i - 2);
data.add(1);
for (int j = 2; j <= i -1; j++) {
data.add(prev.get(j - 2) + prev.get(j - 1));
}
data.add(1);
pascalTriangle.add(data);
}
}
System.out.println("Pascal Triangle:");
for (ArrayList<Integer> data : pascalTriangle) {
System.out.println(data.toString());
}
}
}
15题输出结果:
15题输出结果16.改进 average 方法,使得调用该方法,至少有一个参数。
这个题,,,,,,略,,,,,额,主要是我也没想好要加什么参数合适。