java动手动脑5(数组)

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<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\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循环。 

 

  

posted @ 2016-11-06 14:58  韩晓凡  阅读(306)  评论(0编辑  收藏  举报