zoukankan      html  css  js  c++  java
  • java 进行超大整数的加减乘除四则运算(自己部分实现BigInteger)

    问题分析:

    加减运算:

    两数进行加减,都可以转为两个基本运算:

    • 两个非负数相加--------------- plusAdd()
     1 private  StringBuffer plusAdd(String strNum1,String strNum2){
     2         //把两个数字字符串倒置,并存入字符数组
     3         char [] num1 = new StringBuffer(strNum1).reverse().toString().toCharArray();
     4         char [] num2 = new StringBuffer(strNum2).reverse().toString().toCharArray();
     5         int maxLength = Math.max(num1.length,num2.length);
     6         int minLength = Math.min(num1.length,num2.length);
     7         //n位和m位的非负整数相加的和,要么是max(n,m)位,要么是max(n,m)+1位。
     8         StringBuffer value = new StringBuffer();
     9     
    10         /*--------------计算和数开始------------------------*/
    11         int i,jinWei=0;
    12         for(i=0;i<minLength;i++){
    13             int temp = jinWei + num1[i] - '0'  +num2[i] - '0';
    14             value.append((char)(temp%10 + '0')); 
    15             jinWei = temp/10;
    16         }
    17         if(maxLength == num1.length)
    18             jinWei = oneBitAdd(jinWei,num1,i,maxLength,value);
    19         else
    20             jinWei = oneBitAdd(jinWei,num2,i,maxLength,value);
    21         if(jinWei != 0)
    22              value.append((char)(jinWei +'0'));
    23         /*--------------计算和数结束------------------------*/
    24         return deleteZero(value).reverse();
    25     }
    • 一个较大的非负数减去一个不大于前一个数的非负数 ----- plusMinus()
     1 private  StringBuffer plusMinus(String bigNumStr,String smallNumStr){
     2         //把两个数字字符串倒置,并存入字符数组
     3         char [] num1 = new StringBuffer(bigNumStr).reverse().toString().toCharArray();
     4         char [] num2 = new StringBuffer(smallNumStr).reverse().toString().toCharArray();
     5         StringBuffer value = new StringBuffer();
     6         
     7         /*--------------计算减法开始------------------------*/    
     8         int i,temp,jieWei = 0;
     9         for(i = 0;i<smallNumStr.length();i++){
    10             temp = num1[i]  - jieWei - num2[i];
    11             jieWei = oneBitMinus(temp,value,i);    
    12         }
    13         //处理较大数比较小数多出来的位
    14         for(;i<bigNumStr.length();i++){
    15             temp = num1[i] - '0' - jieWei;
    16             jieWei = oneBitMinus(temp,value,i);
    17         }
    18         /*--------------计算减法结束------------------------*/
    19         return deleteZero(value).reverse();
    20     }

    假设num1  , num2 分别为被加数 、加数,则最终结果只可能是以下情况:

    1. num1  非负数    num2  非负数
    2. num1  负数        num2  负数            、
    3. num1  非负数    num2  负数              
    4. num1  负数        num2  非负数

    上面四种情况可以转为:

    1. plusAdd(num1,num2)
    2. - plusAdd(- num1,- num2)  
    3. plusMinus(num1,- num2)
    4. plusMinus(num2,- num2)

     

    减法类似。

    乘法运算:

    乘法也可以转化为一个基本运算: 两个正整数相乘----plusMulti()

    private  StringBuffer plusMulti(StringBuffer str1,StringBuffer str2) {
            //新建两个StringBuffer,存储两数的前后倒置。
            StringBuffer num1 = new StringBuffer(str1.substring(0)).reverse();
            StringBuffer num2 = new StringBuffer(str2.substring(0)).reverse();
            StringBuffer array = new StringBuffer();
            //n位数和m位数相乘,得到的结果的位数只能是n+m或者n+m-1。
            int len = str1.length() + str2.length();
            for(int i = 0;i<len-1;i++){
                array.append('0');
            }
            //标志n+m位
            array.append('+'); 
            
            //模拟竖式计算    
            for(int i = 0,j,jinWei = 0 ; i < str2.length() ; i++){
                jinWei = 0; //进位归位
                for(j = 0 ; j < str1.length() ; j++){
                    int temp = (num2.charAt(i)-'0')*(num1.charAt(j)-'0') + jinWei + array.charAt(i+j) - '0';
                    array.setCharAt(i+j,(char)(temp%10 + '0'));
                    jinWei = temp /10;
                }
                if(jinWei !=0)
                    array.setCharAt(i+j, (char)(jinWei +'0'));
            }
            if(array.charAt(len -1) == '+')
                array.setLength(len-1);
            return  array.reverse();
        }

    各种情况只和plusMulti()有正负号的区别。其中一个数为0时,直接返回0即可。     

    除法运算:

    模拟手算除法的过程。

    除法也可以转化为一个基本运算,两个非负数相除,除数不为0。-------------plusDivide()

     1 private StringBuffer plusDivide(String str1,String str2){  //str1  /   str2
     2         StringBuffer division = new StringBuffer();
     3         StringBuffer remain   = new StringBuffer();
     4         
     5         int end = 0;
     6         boolean  flag = false;            //标志在不够除时,是否需要上0。
     7         while(end < str1.length()){
     8             remain.append(str1.charAt(end));    //从被除数那里取一位
     9             if(Str1ThanStr2(remain.toString(),str2)){//能整除
    10                 flag = true;
    11                 int fullNum = Greatst(remain,str2);
    12                 StringBuffer fullNumStr2 = plusMulti(new StringBuffer(str2),new StringBuffer(""+fullNum));
    13                 division.append(""+fullNum);
    14                 remain = plusMinus(remain.toString(),fullNumStr2.toString());
    15             }
    16             else if(flag)//不够除,补0
    17                 division.append("0");
    18             if(remain.toString().equals("0"))
    19                 remain.setLength(0);
    20             end++;
    21         }
    22         if(division.length() == 0){
    23             return division.append('0');
    24         }
    25         return division;
    26     }

    各种情况至于plusDivide()只有符号的区别,除数为0时,特别处理下即可。

    代码简介:

    对外开放了四个方法:加减乘除。

    •         public MyBigInteger Minus(MyBigInteger t)       减法
    •         public MyBigInteger Multi(MyBigInteger t)         乘法
    •         public MyBigInteger Add(MyBigInteger str)         加法
    •         public MyBigInteger Divide(MyBigInteger t)        除法

    测试:

    乘法:进行10000!的运算,与用BigInteger类得到的结果一样。四种情况都测试了,结果一致。至少一个数为0时,也得到了了0。值得信赖!

    其他的三种,测试没有乘法详细,如果有bug欢迎指出。

    下面的main函数中,提供了

    (175 + 231 - 143)*(-1978654)/(-54)

     

    完整代码如下:

      1  
      2 public class MyBigInteger {
      3     private StringBuffer data;
      4     
      5     
      6     public MyBigInteger(){
      7         data = new StringBuffer("0");
      8     }
      9     public MyBigInteger(String str){
     10         data = new StringBuffer(str);
     11     }
     12     public MyBigInteger(StringBuffer str){
     13         data = new StringBuffer(str);
     14     }
     15  
     16     public int length(){
     17         return data.length();
     18     }
     19     public String toString(){
     20         return data.toString();
     21     }
     22     
     23     public boolean equals(Object obj){
     24         return data == ((MyBigInteger)obj).data;
     25     }
     26     
     27     /**
     28      * 功能:进行两个非负整数的相加
     29      */
     30     private  StringBuffer plusAdd(String strNum1,String strNum2){
     31         //把两个数字字符串倒置,并存入字符数组
     32         char [] num1 = new StringBuffer(strNum1).reverse().toString().toCharArray();
     33         char [] num2 = new StringBuffer(strNum2).reverse().toString().toCharArray();
     34         int maxLength = Math.max(num1.length,num2.length);
     35         int minLength = Math.min(num1.length,num2.length);
     36         //n位和m位的非负整数相加的和,要么是max(n,m)位,要么是max(n,m)+1位。
     37         StringBuffer value = new StringBuffer();
     38     
     39         /*--------------计算和数开始------------------------*/
     40         int i,jinWei=0;
     41         for(i=0;i<minLength;i++){
     42             int temp = jinWei + num1[i] - '0'  +num2[i] - '0';
     43             value.append((char)(temp%10 + '0')); 
     44             jinWei = temp/10;
     45         }
     46         if(maxLength == num1.length)
     47             jinWei = oneBitAdd(jinWei,num1,i,maxLength,value);
     48         else
     49             jinWei = oneBitAdd(jinWei,num2,i,maxLength,value);
     50         if(jinWei != 0)
     51              value.append((char)(jinWei +'0'));
     52         /*--------------计算和数结束------------------------*/
     53         return deleteZero(value).reverse();
     54     }
     55     /**
     56      * 进位加上字符数组一部分
     57      * @return
     58      */
     59     private int oneBitAdd(int jinWei,char []array,int beginIndex,int endIndex,StringBuffer value){
     60         int temp;
     61         for(int i = beginIndex;i<endIndex;i++){
     62             temp = jinWei + array[i] - '0';
     63             jinWei = temp/10;
     64             value.append((char)(temp%10+'0'));
     65         }
     66         return jinWei;
     67     }
     68     
     69     /**
     70      * 功能:较大的非负整数bigNumStr减去较小的非负整数smallNumStr
     71      */
     72     private  StringBuffer plusMinus(String bigNumStr,String smallNumStr){
     73         //把两个数字字符串倒置,并存入字符数组
     74         char [] num1 = new StringBuffer(bigNumStr).reverse().toString().toCharArray();
     75         char [] num2 = new StringBuffer(smallNumStr).reverse().toString().toCharArray();
     76         StringBuffer value = new StringBuffer();
     77         
     78         /*--------------计算减法开始------------------------*/    
     79         int i,temp,jieWei = 0;
     80         for(i = 0;i<smallNumStr.length();i++){
     81             temp = num1[i]  - jieWei - num2[i];
     82             jieWei = oneBitMinus(temp,value,i);    
     83         }
     84         //处理较大数比较小数多出来的位
     85         for(;i<bigNumStr.length();i++){
     86             temp = num1[i] - '0' - jieWei;
     87             jieWei = oneBitMinus(temp,value,i);
     88         }
     89         /*--------------计算减法结束------------------------*/
     90         return deleteZero(value).reverse();
     91     }
     92     /**
     93      * 删去多余的0
     94      */
     95     private StringBuffer deleteZero(StringBuffer str){
     96         int num=0;
     97         for(int i = str.length()-1;i>=0;i--){
     98             if(str.charAt(i) == '0')
     99                 num++;
    100             else
    101                 break;
    102         }
    103         if(num != str.length()) 
    104             str.setLength(str.length()-num);
    105         else
    106             str = new StringBuffer("0");
    107         return str;
    108     }
    109     /**
    110      * 一位减法
    111      */
    112     private int oneBitMinus(int flag,StringBuffer value,int num){
    113         int jieWei;
    114         if(flag <0){
    115             value.append((char)(10 +flag + '0'));
    116             jieWei = 1;
    117         }
    118         else{
    119             jieWei = 0;
    120             value.append((char)(flag + '0'));
    121         }
    122         return jieWei;
    123     }
    124     
    125     /**
    126      * 名称:内部调用的减法。
    127      * 功能:两个非负数相减。
    128      * 结果:返回运算结果的前后倒置。
    129      */
    130     private  StringBuffer innerMinus(String str1,String str2){
    131         StringBuffer temp;
    132         if(Str1ThanStr2(str1,str2))//若str1更大
    133             temp =  plusMinus(str1,str2);
    134         else{
    135             temp = plusMinus(str2,str1);
    136             if(!temp.toString().equals("0"))
    137                  temp.reverse().append('-').reverse();
    138         }
    139         return temp;
    140     }
    141     /**
    142      * 判断正负
    143      * true -- 非负      false -- 负
    144      */
    145     public boolean isNoNegative(MyBigInteger t){
    146         if(t.data.charAt(0) == '-')
    147             return false;
    148         return true;
    149     }
    150     
    151     /**
    152      * 对外开放的加法接口
    153      * 计算str1 + str2
    154      */
    155     public MyBigInteger Add(MyBigInteger str){
    156         //两数都非负
    157         if(isNoNegative(this) && isNoNegative(str)) 
    158                 data = plusAdd(data.toString(),str.data.toString());
    159         else if(!isNoNegative(this) && !isNoNegative(str)){
    160                 StringBuffer temp = plusAdd(data.substring(1),str.data.substring(1));
    161                 if(!temp.toString().equals("0"))
    162                     data =  temp.reverse().append('-').reverse();
    163                 else
    164                     data = temp;
    165             }
    166         else if(!isNoNegative(this) && isNoNegative(str))
    167                 data = innerMinus(str.data.toString(),data.substring(1));
    168         else
    169                 data = innerMinus(data.toString(),str.data.substring(1));
    170         return this;
    171     }
    172     /**
    173      * 对外开放的减法。
    174      * 计算str1 - str2
    175      */
    176     public MyBigInteger Minus(MyBigInteger t){
    177             //两数都为正。
    178             if(isNoNegative(this) && isNoNegative(t))
    179                 data = innerMinus(this.data.toString(),t.data.toString());    
    180             //两数都为负时,需要对innerMinus得到的结果逆转正负。
    181             else if(!isNoNegative(this) && !isNoNegative(t))  
    182                 data = innerMinus(t.data.substring(1),data.substring(1));        
    183             //this 为负,t为非负。
    184             else if(!isNoNegative(this) && isNoNegative(t)){
    185                 StringBuffer temp = plusAdd(data.substring(1),t.data.toString());
    186                 if(!temp.toString().equals("0"))    
    187                     data = temp.reverse().append('-').reverse();
    188                 else
    189                     data = temp;
    190             }
    191             //this 为非负,str为负。
    192             else
    193                 data = plusAdd(data.toString(),t.data.substring(1).toString());    
    194             return this;
    195     }
    196     
    197     /**
    198      * 内部使用的两个正整数乘法
    199      */
    200     private  StringBuffer plusMulti(StringBuffer str1,StringBuffer str2) {
    201         //新建两个StringBuffer,存储两数的前后倒置。
    202         StringBuffer num1 = new StringBuffer(str1.substring(0)).reverse();
    203         StringBuffer num2 = new StringBuffer(str2.substring(0)).reverse();
    204         StringBuffer array = new StringBuffer();
    205         //n位数和m位数相乘,得到的结果的位数只能是n+m或者n+m-1。
    206         int len = str1.length() + str2.length();
    207         for(int i = 0;i<len-1;i++){
    208             array.append('0');
    209         }
    210         //标志n+m位
    211         array.append('+'); 
    212         
    213         //模拟竖式计算    
    214         for(int i = 0,j,jinWei = 0 ; i < str2.length() ; i++){
    215             jinWei = 0; //进位归位
    216             for(j = 0 ; j < str1.length() ; j++){
    217                 int temp = (num2.charAt(i)-'0')*(num1.charAt(j)-'0') + jinWei + array.charAt(i+j) - '0';
    218                 array.setCharAt(i+j,(char)(temp%10 + '0'));
    219                 jinWei = temp /10;
    220             }
    221             if(jinWei !=0)
    222                 array.setCharAt(i+j, (char)(jinWei +'0'));
    223         }
    224         if(array.charAt(len -1) == '+')
    225             array.setLength(len-1);
    226         return  array.reverse();
    227     }
    228     /**
    229      * 对外开放的乘法
    230      */
    231     public MyBigInteger Multi(MyBigInteger t){
    232         //两数至少有一个为0
    233         if(data.toString().equals("0") || t.data.toString().equals("0"))
    234             data = new StringBuffer("0");
    235         else{
    236             //两数都是正数
    237             if(isNoNegative(this) && isNoNegative(t))
    238                 data = plusMulti(data,t.data).reverse();
    239             //两数都是负数
    240             else if(!isNoNegative(this) && !isNoNegative(t))
    241                 data = plusMulti(new StringBuffer(data.substring(1)),new StringBuffer(t.data.substring(1)));    
    242             
    243             //两数一正一负
    244             else if(isNoNegative(this) && !isNoNegative(t))
    245                 data =     plusMulti(data,new StringBuffer(t.data.substring(1))).reverse().append('-').reverse();    
    246             else
    247                 data = plusMulti(new StringBuffer(data.substring(1)),t.data).reverse().append('-').reverse();
    248         }
    249         return this;
    250     }
    251     /**
    252      * 两个非负数相除,除数不为0
    253      * 返回:没有前后倒置的正确的结果
    254      */
    255     private StringBuffer plusDivide(String str1,String str2){
    256         StringBuffer division = new StringBuffer();
    257         StringBuffer remain   = new StringBuffer();
    258         
    259         int end = 0;
    260         boolean  flag = false;
    261         while(end < str1.length()){
    262             remain.append(str1.charAt(end));
    263             if(Str1ThanStr2(remain.toString(),str2)){//能整除
    264                 flag = true;
    265                 int fullNum = Greatst(remain,str2);
    266                 StringBuffer fullNumStr2 = plusMulti(new StringBuffer(str2),new StringBuffer(""+fullNum));
    267                 division.append(""+fullNum);
    268                 remain = plusMinus(remain.toString(),fullNumStr2.toString());
    269             }
    270             else if(flag)//不够除,补0
    271                 division.append("0");
    272             if(remain.toString().equals("0"))
    273                 remain.setLength(0);
    274             end++;
    275         }
    276         if(division.length() == 0){
    277             return division.append('0');
    278         }
    279         return division;
    280     }
    281     /**
    282      * 对外开放的减法
    283      */
    284     public MyBigInteger Divide(MyBigInteger t){
    285         if(t.data.toString().equals("0"))
    286             System.out.println("除零异常");
    287         else{
    288             if(isNoNegative(this) && isNoNegative(t))
    289                 data = plusDivide(data.toString(),t.data.toString());
    290             else if(!isNoNegative(this) && !isNoNegative(t)){
    291                 data = plusDivide(data.substring(1),t.data.substring(1));
    292             }
    293             else{
    294                 StringBuffer temp;
    295                 if(!isNoNegative(this) && isNoNegative(t))
    296                      temp = plusDivide(data.substring(1),t.data.toString());
    297                 else
    298                      temp = plusDivide(data.toString(),t.data.substring(1));
    299                 if(temp.toString().equals("0"))
    300                     data = temp;
    301                 else
    302                     data = temp.reverse().append('-').reverse();
    303             }
    304         }
    305         return this;
    306     }
    307  
    308     /*
    309      * 找出最大
    310      */
    311     private  int Greatst(StringBuffer str1,String str2){
    312         for(int i = 1;i<10;i++){
    313             StringBuffer num2 = new StringBuffer(str2);
    314             for(int j =0;j<i;j++){//(i +1)倍
    315                 num2 = plusAdd(num2.toString(),str2);
    316             }
    317             if(!Str1ThanStr2(str1.toString(),num2.toString())){
    318                 return i;
    319             }
    320         }
    321         return -1;
    322     }
    323     /**
    324      * 判断str1、str2的大小
    325      * 返回:str1>= str2 -----true           
    326      *      str1< str2 -----false
    327      */
    328     private static boolean Str1ThanStr2(String str1,String str2){
    329         boolean flag;//1 代表str1大些;2代表str2大些
    330         //判断两个非负数,谁大。
    331         if(str1.length() == str2.length()){
    332             if(str1.compareTo(str2)<0)
    333                 flag = false;
    334             else   
    335                 flag =true;
    336         }
    337         else{
    338             if(str1.length() >str2.length())
    339                 flag = true;
    340             else
    341                 flag = false;
    342         }
    343         return flag;
    344     }
    345     
    346     
    347     public static void main(String[] args) {
    348         MyBigInteger a1 = new MyBigInteger("175");
    349         MyBigInteger a2 = new MyBigInteger("231");
    350         MyBigInteger a3 = new MyBigInteger("143");
    351         MyBigInteger a4 = new MyBigInteger("-1978654");
    352         MyBigInteger b = new MyBigInteger("-54");
    353         MyBigInteger b1 = new MyBigInteger("0");
    354         //175 + 231 - 143
    355         System.out.println(a1.Add(a2).Minus(a3));
    356         //(175 + 231 - 143)*(-1978654)
    357         System.out.println(a1.Multi(a4));
    358         //(175 + 231 - 143)*(-1978654)/(-54)
    359         System.out.println(a1.Divide(b));
    360         //0
    361         System.out.println(a1.Multi(b1));
    362     }
    363 }
  • 相关阅读:
    子类、变换cocos2dx 学习点滴(5) Scene,Director, Layer 和 Spriteby小雨
    宋体、代码iOS网络编程实践NSStream实现TCP Socket iPhone客户端by小雨
    软件、双核基于全志A10\A20产品跑分测试结果对比by小雨
    开机、问题MocorDroid拔掉电池开机比正常关机后开机慢1分钟问题by小雨
    服务、启动Android音频系统之AudioFlinger(一)by小雨
    设备、线程Android音频系统之AudioFlinger(二)by小雨
    数据、循环Android音频系统之AudioFlinger(三)by小雨
    声音、音频Android音频系统之AudioPolicyServiceby小雨
    判断、转载【Cocos2DX 】初窥门径(8)判断精灵点击by小雨
    文件、格式【Cocos2DX 】初窥门径(10)解决中文乱码by小雨
  • 原文地址:https://www.cnblogs.com/cq0143/p/10330602.html
Copyright © 2011-2022 走看看