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:\n";
for (int i = 0; i < a.length; i++)
output += " " + a[i];
output += "\n\nEffects of passing array " + "element call-by-value:\n"+ "a[3] before modifyElement: " + a[3];
modifyElement(a[3]);
output += "\na[3] after modifyElement: " + a[3];
output += "\n Effects of passing entire array by reference";
modifyArray(a); // array a passed call-by-reference
output += "\n\nThe values of the modified array are:\n";
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("\n");
}
}
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
{
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]-=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
{
int i=0;
for(i=0;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\tValue\n";
for ( int i = 0; i < n.length; i++ )
{
output += i + "\t" + n[ i ] + "\n";
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循环。