《写给大忙人看的 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 方法,使得调用该方法,至少有一个参数。

这个题,,,,,,略,,,,,额,主要是我也没想好要加什么参数合适。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容