上篇分享了一下数字转汉字的小功能,这里再分享一下大数相乘,相加,相减的功能。其他的不做过多的铺垫了,我先讲一下各个功能的计算原理。
<强>Ⅰ。乘法运算强>
为什么先说乘法运算,因为我先做了乘法运算。其实思路也是很多的,但是最终我参考了网络上的一种计算方案,然后做了很多的修改。感觉这个在思路上应该是比较简单的。
简单点说:把数拆分成整数小数分别进行乘法运算,然后将结果放入一个特定长度的数组中,在放入是要计算存放的偏移位置,最后再对这个进行处理(进位,标记等),得到最终的结果。
是不是有点晕。请我详细说一下吧:
-
<李>首先还得把数都拆成整数+小数,然后采用的是(x1 + x2) (y1 + y2)=x + x1y2 + x2y1 + x。这种方式来计算的,这样来算,都变成了整数的运算了。要简单很多。但是4个结果怎么累加起来计算呢,这就是第二步。
李> <李>要申明一个int数组,长度=整数长度和+小数长度和+ 1(小数点占1位)。通过实验,我们可以看到任意2个整数相乘结果都不会超过这两个数的长度和。
李> <李>人为计算乘法的时候就是按右向左一位一位的计算的(低位对齐),所以为了对齐低位,我们将整数和小数全部反转,并且转化为字符数组,方便运算。然后进行4次乘法。
李> <李>按位进行乘法运算,采用双层为循环完成这个操作。这里最为天才的想法就是——不进位。当然必须得弄清楚整数相乘放在数组的哪些个位置,小数相乘存放的开始位置,以及整数和小数相乘结果存放的开始位置。
李> <李>处理结果集合,将祝辞=10的做进位处理。
李> <李>这一步也是很有才的想法,对小数点位置进行标记,而不是直接替换成”。”(int数组也不能直接设定(/鮘))。
李> <李>有了第6步的想法,就有了第7步的做法,处理整数部分头部的0和小数部分末尾的0,都是无效数字,这里同样采用标记的方式来处理
李> <李>最后将结果集合进行反转输出,遇到小数点标记和无效0标记直接替换和跳过。李>
这就是基本的思路了。后面又再次基础上加上了负数的判断,数字格式的判断等,自己看注释就可以明白了。
代码如下:
//标记为小数点 私有静态最终int点=-99;//标记为无效数字 私有静态最终int无效=-100;/* * *大数乘法 * * @param第一个数 * @param b第二个数 * @return最终结果 */公共静态字符串相乘(字符串,字符串b) {//检查数字格式 checkNum(一个); checkNum (b);//标记最终结果是否为负的值 布尔-=false;//判断是否有带着-号 如果(a.startsWith (“-”) | | b.startsWith (“-”)) {//判断是否全带着-号 如果(a.startsWith (“-”),,b.startsWith (“-”)) { 其他}{//只有1个带着号,则结果为负的值 -=true; } 如果(a.startsWith (“-”)) { 一个=a.substring (1); } 如果(b.startsWith (“-”)) { b=b.substring (1); } }//获取a、b的整数和小数部分 字符串a_int=getInt (); 字符串a_fraction=getFraction(一个); 字符串b_int=getInt (b); 字符串b_fraction=getFraction (b);//计算小数部分的总长度 int len_fraction=a_fraction.length () + b_fraction.length ();//a、b两个数乘积的最大位数不会超过总位数之和+小数点(1位) int len=len_fraction + a_int.length b_int.length () + () + 1;//创建结果数组 int[]结果=new int (len);//默认全为0//为了方便计算,去掉小数点(最后在结果中加上小数点)//并将高低位对调(反转是为了低位对齐),最终转化为字符数组 char [] s_a_int=reverseStr (a_int); char [] s_a_fraction=reverseStr (a_fraction); char [] s_b_int=reverseStr (b_int); char [] s_b_fraction=reverseStr (b_fraction);//将a、b都拆分成整数+小数,然后//采用(x1 + x2) (y1 + y2)=x + x1y2 + x2y1 + x公式,分别计算乘积 乘(s_a_int s_b_int len_fraction,结果); 乘(s_a_int s_b_fraction (len_fraction-s_b_fraction.length),结果); 乘(s_b_int s_a_fraction (len_fraction-s_a_fraction.length),结果); 乘(s_a_fraction s_b_fraction 0,结果);//处理结果集合,如果是大于10的就向前一位进位,本身进行除10取余 accumulateResultArrays(结果);//标记小数点位置 markDot (len_fraction,结果);//切掉无用的0 cutUnusedZero (len_fraction,结果);//然后将数据反转 返回(- # 63;“-”:" ")+ reverseResult(结果); }/* * *反转字符串,并转化为数组 * * @param年代原字符串 * @return */私有静态char [] reverseStr (String s) { 返回新StringBuffer (s) .reverse () .toString () .toCharArray (); }/* * *计算2个数的每一位的乘积,放入到对应的结果数组中(未进位) * * @param第一个数 * @param b第二个数 * @param开始开始放入的偏移位置 * @param结果结果数组 */私有静态孔隙乘(char [], char [] b, int, int[]结果){//计算结果集合 for (int i=0;我& lt;a.length;我+ +){ for (int j=0;j & lt;b.length;j + +) { 结果(我+ j +) +=(int)([我],' 0 ')* (int) (b [j], ' 0 '); } } }/* * *累加每一位,超过10则然后进位 * * @param结果结果数组 */私有静态孔隙accumulateResultArrays (int[]结果){ for (int i=0;我& lt;result.length;我+ +){ 如果结果[我]祝辞=10){ 结果(i + 1)(我)/10 +=结果; 结果[我]%=10; } } }/* * *标记小数点位置 * * @param len_fraction小数长度 * @param结果结果数组(反转的) */私有静态孔隙markDot (int len_fraction, int[]结果){ 如果(len_fraction> 0) {//标记小数点位置 for (int i=结果。长度是1;我在;len_fraction;我(){ 结果[我]=结果(张); } 结果[len_fraction]=点;//标记小数点位置 } }/* * *去掉不必要的0(包括整数最前面的和小数最后面的0) * * @param len_fraction小数长度 * @param结果结果数组 */私有静态孔隙cutUnusedZero (int len_fraction, int[]结果){//去掉小数部分不必要的0 布尔flag_0_fraction=true;//标记一直是0 for (int i=0;iJava常用数字工具类大数乘法,加法,减法运算(2)