1、阅读并运行示例PassArray.java,观察并分析程序输出的结果,小结。
PassArray.java: public class PassArray { public static void main(String[] args) { int a[] = { 1, 2, 3, 4, 5 }; String output = "The values of the original array are: "; for (int i = 0; i < a.length; i++) output += " " + a[i]; output += " Effects of passing array " + "element call-by-value: "+ "a[3] before modifyElement: " + a[3]; modifyElement(a[3]); output += " a[3] after modifyElement: " + a[3]; output += " Effects of passing entire array by reference"; modifyArray(a); // array a passed call-by-reference output += " The values of the modified array are: "; for (int i = 0; i < a.length; i++) output += " " + a[i]; System.out.println(output); } public static void modifyArray(int b[]) { for (int j = 0; j < b.length; j++) b[j] *= 2; } public static void modifyElement(int e) { e *= 2; } }
运行结果:
小结:按引用传递与按值传送数组类型方法参数的最大关键在于:
使用前者时,如果方法中有代码更改了数组元素的值,实际上是直接修改了原始的数组元素。使原始数组中的数据元素改变,所以输出原来数组的数变化。
使用后者则没有这个问题,方法体中修改的仅是原始数组元素的一个拷贝。并不改变原来的数据,所以输出后还是原来的数。
2、阅读QiPan.java示例程序了解如何利用二维数组和循环语句绘制五子棋盘。
QiPan.java: import java.io.*; public class QiPan { //定义一个二维数组来充当棋盘 private String[][] board; //定义棋盘的大小 private static int BOARD_SIZE = 15; public void initBoard() { //初始化棋盘数组 board = new String[BOARD_SIZE][BOARD_SIZE]; //把每个元素赋为"╋",用于在控制台画出棋盘 for (int i = 0 ; i < BOARD_SIZE ; i++) { for ( int j = 0 ; j < BOARD_SIZE ; j++) { board[i][j] = "╋"; } } } //在控制台输出棋盘的方法 public void printBoard() { //打印每个数组元素 for (int i = 0 ; i < BOARD_SIZE ; i++) { for ( int j = 0 ; j < BOARD_SIZE ; j++) { //打印数组元素后不换行 System.out.print(board[i][j]); } //每打印完一行数组元素后输出一个换行符 System.out.print(" "); } } public static void main(String[] args)throws Exception { QiPan gb = new QiPan(); gb.initBoard(); gb.printBoard(); //这是用于获取键盘输入的方法 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String inputStr = null; System.out.println("请输入您下棋的座标,应以x,y的格式:"); //br.readLine():每当在键盘上输入一行内容按回车,刚输入的内容将被br读取到。 while ((inputStr = br.readLine()) != null) { //将用户输入的字符串以逗号(,)作为分隔符,分隔成2个字符串 String[] posStrArr = inputStr.split(","); //将2个字符串转换成用户下棋的座标 int xPos = Integer.parseInt(posStrArr[0]); int yPos = Integer.parseInt(posStrArr[1]); //把对应的数组元素赋为"●"。 gb.board[xPos - 1][yPos - 1] = "●"; /* 电脑随机生成2个整数,作为电脑下棋的座标,赋给board数组。 还涉及 1.座标的有效性,只能是数字,不能超出棋盘范围 2.如果下的棋的点,不能重复下棋。 3.每次下棋后,需要扫描谁赢了*/ gb.printBoard(); System.out.println("请输入您下棋的座标,应以x,y的格式:"); } } }
结果:
总结:首先用二维数组初始化一个棋盘board,定义棋盘的大小BOARD_SIZE,然后利用for循环,输出棋盘并用“+”填充棋盘,其中行是一个循环,而列的循环在行里面。然后打印棋盘,行一个循环,列是一个循环,列的循环在行里面。打印元素个数满一行才输出换行,所以输出换行应该在行循环里面在列循环外面。然后在主函数中定义一个Qipan类的对象gd,调用初始化和打印棋盘的函数,用BufferedReader用于键盘上的输入,然后将输入值的位置填充为“●”
3、请编写一个程序将一个整数转换为汉字读法字符串。比如“1123”转换为“一千一百二十三”。
public class Num2Rmb { private String[] hanArr = {"零" , "壹" , "贰" , "叁" , "肆" , "伍" , "陆" , "柒" , "捌" , "玖"}; private String[] unitArr = {"十" , "百" , "千","万","十万","百万"}; /** * 把一个四位的数字字符串变成汉字字符串 * @param numStr 需要被转换的四位的数字字符串 * @return 四位的数字字符串被转换成的汉字字符串。 */ private String toHanStr(String numStr) { String result = ""; int numLen = numStr.length(); //依次遍历数字字符串的每一位数字 for (int i = 0 ; i < numLen ; i++ ) { //把char型数字转换成的int型数字,因为它们的ASCII码值恰好相差48 //因此把char型数字减去48得到int型数字,例如'4'被转换成4。 int num = numStr.charAt(i) - 48; //如果不是最后一位数字,而且数字不是零,则需要添加单位(千、百、十) if ( i != numLen - 1 && num != 0) { result += hanArr[num] + unitArr[numLen - 2 - i]; } //否则不要添加单位 else { //上一个数是否为“零”,不为“零”时就添加 if(result.length()>0 && hanArr[num].equals("零") && result.charAt(result.length()-1)=='零') continue; result += hanArr[num]; } } //只有个位数,直接返回 if(result.length()==1) return result; int index=result.length()-1; while(result.charAt(index)=='零'){ index--; } if(index!=result.length()-1) return result.substring(0,index+1); else { return result; } } public static void main(String[] args) { Num2Rmb nr = new Num2Rmb(); System.out.println("只支持整数(0~百万)"); //测试把一个四位的数字字符串变成汉字字符串 System.out.println(nr.toHanStr("0")); System.out.println(nr.toHanStr("1")); System.out.println(nr.toHanStr("10")); System.out.println(nr.toHanStr("15")); System.out.println(nr.toHanStr("110")); System.out.println(nr.toHanStr("123")); System.out.println(nr.toHanStr("105")); System.out.println(nr.toHanStr("1000")); System.out.println(nr.toHanStr("1100")); System.out.println(nr.toHanStr("1110")); System.out.println(nr.toHanStr("1005")); System.out.println(nr.toHanStr("1105")); System.out.println(nr.toHanStr("1111")); System.out.println(nr.toHanStr("10000")); System.out.println(nr.toHanStr("10001")); System.out.println(nr.toHanStr("10011")); System.out.println(nr.toHanStr("10111")); System.out.println(nr.toHanStr("11111")); System.out.println(nr.toHanStr("11000")); System.out.println(nr.toHanStr("11100")); System.out.println(nr.toHanStr("11110")); System.out.println(nr.toHanStr("101110")); System.out.println(nr.toHanStr("1001110")); } }
结果:
分析:
定义两个数组,一个是所有数字的大写,另一个是个十百千万单位,用charAt()依次遍历数字字符串的每一位数字,把char型数字转换成的int型数字,因为它们的ASCII码值恰好相差48把char型数字减去48得到int型数字,例如'4'被转换成4。如果不是最后一位数字,而且数字不是零,则需要添加单位(千、百、十),否则就不添加单位,上一个数是否为“零”,不为“零”时就添加只有个位数,直接返回。
更进一步,能否将数字表示的金额改为“汉字表达? 比如将“¥123.52”转换为“壹佰贰拾叁元伍角贰分”?
public class Trans2RMB { public static void main(String[] args) { Trans2RMB t2r = new Trans2RMB(); String t2=t2r.inputNum(); String t3=t2r.splitNum(t2); String s=t2r.cleanZero(t3); System.out.println("将数字转换成中文金额的大写形式为:" + s); } // 从命令行接收一个数,在其中调用 checkNum() 方法对其进行验证,并返回相应的值 private String inputNum() { String s = null; System.out.println("请输入一个数字(精确到小数点后两位):"); // 从命令行输入这个浮点数 java.util.Scanner scanner = new java.util.Scanner(System.in); s = scanner.next(); // 关闭这个Scanner scanner.close(); // 判断用户输入是否合法 // 若合法,返回这个值;若非法返回 "0" if(this.checkNum(s)==true) { return s; } else { System.out.println("输入错误,请检查!"); return ""; } } //判断用户输入的数据是否合法,用户只能输入大于零的数字,不能输入其它字符 private boolean checkNum(String s) { // 如果用户输入的数里有非数字字符,则视为非法数据,返回 false float f='s'-48; // 如果这个数小于零则视为非法数据,返回 false if(f < 0) { System.out.println("输入错误,请检查!"); return false; } else { return true; } } //把用户输入的数以小数点为界分割开来,并调用 numFormat() 方法进行相应的中文金额大写形式的转换 //注:传入的这个数应该是经过 roundString() 方法进行了四舍五入操作的 private String splitNum(String s) { // 以小数点为界分割这个字符串 int index = s.indexOf(".");//获取小数点的位置 String intOnly = s.substring(0, index);//整数部分(0到小数点位置的部分) String part1 = this.numFormat(1, intOnly); // 截取并转换这个数的小数部分 String smallOnly = s.substring(index + 1); String part2 = this.numFormat(0, smallOnly); // 把转换好了的整数部分和小数部分重新拼凑一个新的字符串 String newS = part1 + part2; return newS; } // 把传入的数转换为中文金额大写形式 private String numFormat(int flag, String s) { int sLength = s.length(); // 货币大写形式 String bigLetter[] = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"}; // 货币单位 String unit[] = {"元", "拾", "佰", "仟", "万", // 拾万位到仟万位 "拾", "佰", "仟", // 亿位到万亿位 "亿", "拾", "佰", "仟", "万"}; String small[] = {"分", "角"}; // 用来存放转换后的新字符串 String RESTULTS = ""; // 逐位替换为中文大写形式 for(int i = 0; i < sLength; i ++) { if(flag == 1) { // 转换整数部分为中文大写形式(带单位) RESTULTS = RESTULTS + bigLetter[s.charAt(i) - 48] + unit[sLength - i - 1]; } if(flag == 0) { // 转换小数部分(带单位) RESTULTS = RESTULTS + bigLetter[s.charAt(i) - 48] + small[sLength - i - 1]; } } return RESTULTS; } //清楚字符串里多余的零 private String cleanZero(String s) { // 如果用户开始输入了很多 0 去掉字符串前面多余的'零',使其看上去更符合习惯 while(s.charAt(0) == '零') { // 将字符串中的 "零" 和它对应的单位去掉 s = s.substring(2); // 如果用户当初输入的时候只输入了 0,则只返回一个 "零" if(s.length() == 0) { return "零"; } } // 字符串中存在多个'零'在一起的时候只读出一个'零',并省略多余的单位 String clean1[] = {"零仟", "零佰", "零拾"}; String clean2[] = {"零亿", "零万", "零元"}; String clean3[] = {"亿", "万", "元"}; String clean4[] = {"零角", "零分"}; // 第一轮转换把 "零仟", 零佰","零拾"等字符串替换成一个"零" for(int i = 0; i < 3; i ++) { s = s.replaceAll(clean1[i], "零"); } // 第二轮转换考虑 "零亿","零万","零元"等情况 // "亿","万","元"这些单位有些情况是不能省的,需要保留下来 for(int i = 0; i < 3; i ++) { // 当第一轮转换过后有可能有很多个零叠在一起 // 要把很多个重复的零变成一个零 s = s.replaceAll("零零零", "零"); s = s.replaceAll("零零", "零"); s = s.replaceAll(clean2[i], clean3[i]); } // 第三轮转换把"零角","零分"字符串省略 for(int i = 0; i < 2; i ++) { s = s.replaceAll(clean4[i], ""); } // 当"万"到"亿"之间全部是"零"的时候,忽略"亿万"单位,只保留一个"亿" s = s.replaceAll("亿万", "亿"); return s; } }
结果:
4、前面几讲介绍过JDK所提供的BigInteger能完成大数计算,如果不用它,直接使用数组表达大数,你能实现相同的功能吗?
要求:
(1)用你的大数类实现加和减两个功能
(2)阅读BigInteger类源码,弄清楚它是使用什么算法实现加减乘除四种运算的?
(3)通过互联网查找大数运算的相关资料,给你的大数类添加乘、除、求阶乘等其它功能。
public class BigInteger { public static void main(String[] args){ int []a=new int [1000]; int []c=new int[1000]; int []a1=new int [1000]; int []c1=new int[1000]; BigInteger b=new BigInteger(); @SuppressWarnings("resource") java.util.Scanner scanner = new java.util.Scanner(System.in); int x = scanner.nextInt(); int x1=scanner.nextInt(); int m=b.chai(a, x); int n=b.chai(c, x1); int l=b.chai(a1, x); int o=b.chai(c1, x1); b.jia(a,m,c,n); b.jian(a1, l, c1, o); } public int chai(int a[],int x)//将大数x拆分倒着存入数组 例如123->a[0]=3,a[2]=1; { int i=0; while(x>=10) { a[i++]=x%10; x/=10; } a[i]=x; return i;//返回有效数字长度 } public void jia(int num[],int num_i,int b[],int b_i)//num代表的数加上b代表的数,num_i代表num的长度 { if(num_i>=b_i) { int i=0; for(i=0;i<=num_i;i++)//若由函数chai()得来,则为i<=num_i num[i]+=b[i];//一一相加 if(num[i]>=10) //进位运算 { num[i+1]+=num[i]/10; num[i]%=10; } System.out.print("两数和为:"); for(i=num_i;i>=0;i--) System.out.print(num[i]); } if(num_i<b_i) { int i=0; for(i=0;i<=b_i;i++)//若由函数chai()得来,则为i<=num_i b[i]+=num[i];//一一相加 if(b[i]>=10) //进位运算 { b[i+1]+=b[i]/10; b[i]%=10; } System.out.print("两数和为:"); for(i=b_i;i>=0;i--) System.out.print(b[i]); } } public void jian(int num[],int num_i,int b[],int b_i)//num代表的数减去b代表的数 { //默认mun_i>=b_i if(num_i>=b_i) { int i=0; for(i=0;i<num_i;i++) num[i]-=b[i];//一一相减 if(num[i]<0) //补位运算 { num[i]+=10; num[i+1]-=1; } System.out.print("两数差为:"); for(i=num_i;i>=0;i--) System.out.print(num[i]); } if(num_i<b_i) { int i=0; for(i=0;i<b_i;i++) b[i]-=num[i];//一一相减 if(b[i]<0) //补位运算 { b[i]+=10; b[i+1]-=1; } System.out.print("两数差为:"+'-'); for(i=b_i;i>=0;i--) System.out.print(b[i]); } } }
阅读BigInteger类源码,弄清楚它是使用什么算法实现加减乘除四种运算的?
import java.util.*; import java.math.*; public class Test { public static void main(String[] args) { Scanner cin = new Scanner(System.in); //BigInteger类型的常量 BigInteger A = BigInteger.ONE; System.out.println("BigInteger.ONE的结果为 " + A);//1 BigInteger B = BigInteger.TEN; System.out.println("BigInteger.TEN的结果为 " + B);//10 BigInteger C = BigInteger.ZERO; System.out.println("BigInteger.ZERO的结果为 " + C);//0 //初始化 BigInteger c = new BigInteger("12345670",8);//c = 01234567890 ,八进制 System.out.println(c);//2739128 BigInteger d = BigInteger.valueOf(100);//d = 100 BigInteger e = new BigInteger(new byte[]{1,0});//00000001 00000000 System.out.println(e);//256 System.out.println(e.bitCount()); System.out.println(e.bitLength()); //运算 System.out.println("请输入大整数a,b"); while (cin.hasNext()) {//等同于!=EOF BigInteger a = cin.nextBigInteger(); BigInteger b = cin.nextBigInteger(); BigInteger c1 = a.add(b); // 大数加法 System.out.println("加的结果为 " + c1); BigInteger c2 = a.subtract(b); // 大数减法 System.out.println("减的结果为 " + c2); BigInteger c3 = a.multiply(b); // 大数乘法 System.out.println("乘的结果为 " + c3); BigInteger c4 = a.divide(b); // 大数除法 System.out.println("除的结果为 " + c4); BigInteger c5 = a.mod(b); System.out.println("模的结果为 " + c5); BigInteger cc5 = a.remainder(b); System.out.println("余的结果为 " + cc5); BigInteger c6 = a.max(b);// 取最大 System.out.println("最大为 " + c6); BigInteger c7 = a.min(b); // 取最小 System.out.println("最小为 " + c7); BigInteger c8 = a.pow(10); //指数运算 System.out.println("指数运算结果为" + c8); if (a.equals(b)) // 判断是否相等 System.out.println("相等"); else System.out.println("不相等"); BigInteger c10 = a.abs(); // 求绝对值 System.out.println("a的绝对值为 " + c10); BigInteger c11 = a.negate(); // 求相反数 System.out.println("a的相反数为 " + c11); } } }
BigInteger类模拟了所有的int型数学操作,如add()==“+”,divide()==“-”等,但注意其内容进行数学运算时不能直接使用数学运算符进行运算,必须使用其内部方法。而且其操作数也必须为BigInteger型。
5、随机生成10个数,填充一个数组,然后用消息框显示数组内容,接着计算数组元素的和,将结果也显示在消息框中。
源程序:
import javax.swing.*; public class InitArray { public static void main( String args[] ) { String output = ""; // Initializer list specifies number of elements and // value for each element. int n[] = new int[10]; int sum=0; for ( int i = 0; i < n.length; i++ ) { n[i]=(int)(Math.random()*100+1); } output += "Subscript Value "; for ( int i = 0; i < n.length; i++ ) { output += i + " " + n[ i ] + " "; sum=sum+n[i]; } JTextArea outputArea = new JTextArea(); outputArea.setText( output ); JOptionPane.showMessageDialog( null, outputArea, "Initializing an Array with a Declaration", JOptionPane.INFORMATION_MESSAGE ); JOptionPane.showMessageDialog( null, sum,"数组的和为:", JOptionPane.INFORMATION_MESSAGE ); System.exit( 0 ); } }
设计思路:利用random()函数生成随机数,利用for循环将随机数存入数组中,再利用for循环计算出所有数的和,将所有的数和最终求和的结果用对话框的形式输出。
程序流程图:
结果截图:
编程总结:在将随机数输入数组是应该使用for循环输入,一个随机数占用一个内存空间,在计算数组中数的和的时候也需要用for循环。