1. 程式人生 > 其它 >《Java實現大數運算--成電信軟信安數學實驗一》

《Java實現大數運算--成電信軟信安數學實驗一》

大數運算介紹

1.大數指的是超過計算機CPU暫存器表達的數,即超過計算機字長的數。大數基本運算主要指的是對大數進行數論運算,如加、減、乘、除。出於效率原因,一般的大數運算主要指對無符號型別的數進行數論計算。
2.目前主流RSA演算法都建立在512位到1024位的大數運算之上。然而大多數的編譯器只能支援到64位的整數運算,即運算中整數必須小於等於64位,即:0xFFFFFFFFFFFFFFFF,這遠遠達不到RSA的需要,於是需要建立專門的大數運算庫來解決這一問題。
3.最簡單的辦法是將大數當作字串處理,也就是將大數用10進位制字元陣列進行表示,然後模擬人們手工進行“豎式計算”的過程編寫其加減乘除函式。但是這樣做效率很低,因為1024位的大數其10進位制數字個數就有數百個,對於任何一種運算,都需要在兩個有數百個元素的陣列空間上做多重迴圈,還需要許多額外的空間存放計算的進位退位標誌及中間結果。其優點是演算法符合人們的日常習慣,易於理解。
4.另一種方法是將大數當作一個二進位制流進行處理,使用各種移位和邏輯操作來進行加減乘除運算,但是這樣做程式碼設計非常複雜,可讀性很低,難以理解也難以除錯。
5.許多高階語言都支援大數運算(例如Java提供的bigDecimal,python等等)

實驗程式碼

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @author zhangjin
 * @ClassName task_one.java
 * @Description
 * @createTime 2021年11月13日 09:02:00
 */
public class task_one {
    /**
     *
      * @param x
     * @param y
     * @return x>y返回正 x<y返回負 x==y返回0
     */
    public static int compare(String x,String y)
    {
        if(x.length()>y.length()) return 1;
        if(x.length()<y.length()) return -1;
        for(int i=0;i<x.length();i++)
        {
            if(x.getBytes()[i]!=y.getBytes()[i])
            {
                return x.getBytes()[i]-y.getBytes()[i];
            }
        }
        return 0;
    }

    public static String add(String x,String y,String jishu)
    {
        if(compare(x,y)<0) return add(y,x,jishu);   // 保證x>y
        Integer key = Integer.valueOf(jishu);//key為進位制
        int j=y.length();int i=x.length();
        int jinwei=0;
        StringBuilder benwei=new StringBuilder();
        while(j>0)
        {
            int y1=Integer.valueOf(y.substring(j-1,j));//取y的一位
            int x1=Integer.valueOf(x.substring(i-1,i));//取x的一位
            benwei.append((jinwei+x1+y1)%key);//獲取本位並拼接到字串
            jinwei=(x1+y1+jinwei)/key;//獲取進位位
            j--;i--;
        }
        while(i>0)//因為x>y 所以當遍歷完y的所有位數後x尚未遍歷完
        {
            int x1=Integer.valueOf(x.substring(i-1,i));//繼續遍歷x
            benwei.append((x1+jinwei)%key);
            jinwei=(x1+jinwei)/key;
            i--;
        }
        if(jinwei!=0) benwei.append(jinwei);//最後一次進位
        return benwei.reverse().toString();//將求和得到的字串翻轉
    }

    public static String sub(String x,String y,String jishu)
    {
        if(compare(x,y)<0) return sub(y,x,jishu);//確保x>y
        Integer key=Integer.valueOf(jishu);
        int jiewei=0;//借位
        int i=x.length();
        int j=y.length();
        StringBuilder benwei=new StringBuilder();
        while(j>0)
        {
            int y1=Integer.valueOf(y.substring(j-1,j));
            int x1=Integer.valueOf(x.substring(i-1,i));
            benwei.append((x1+key-y1-jiewei)%key);//獲取本位
            jiewei=(x1-jiewei-y1)>=0?0:1;//獲取借位位
            i--;j--;
        }
        while(i>0)//x的位數大於y的位數的情況
        {
            int x1=Integer.valueOf(x.substring(i-1,i));
            benwei.append((x1+key-jiewei)%key);
            jiewei=(x1-jiewei)>=0?0:1;
            i--;
        }
        String res = benwei.reverse().toString().replaceFirst("^0*", "");//去除首位的0
        if(res.equals("")) return "0";//若結果為"00000" 上面去除首位的0後為空字串
        else return res;
    }
    //y為個位數 將y的每一位與x相乘
    public static String mul_one(String x,String y,String jishu){
        int i=x.length();
        int jinwei=0;
        Integer key=Integer.valueOf(jishu);
        StringBuilder benwei=new StringBuilder();
        while(i>0)
        {
            Integer Y=Integer.valueOf(y);
            int x1=Integer.valueOf(x.substring(i-1,i));
            benwei.append((Y*x1+jinwei)%key);
            jinwei=(Y*x1+jinwei)/key;
            i--;
        }
        if(jinwei!=0) benwei.append(jinwei);
        return benwei.reverse().toString();
    }

    public static String mul(String x,String y,String jishu)
    {
        if(compare(x,y)<0) return mul(y,x,jishu);//確保x>y
        int length_y=y.length();
        List<String> res=new ArrayList<String>();
        int i=length_y;
        while(i>0) {
            String s = mul_one(x, y.substring(i - 1, i),jishu);//用y的每一位與x相乘 結果放入陣列
            res.add(s);
            i--;
        }
        for(int j=0;j<length_y;j++)
        {
            String s=res.get(j);//當j=0時表示y的個位數與x相乘 當j=1時表示y的十位數與x相乘 在後續補0相當於移位擴大倍數
            for(int m=0;m<j;m++)
            {
                s=s+"0";
            }
            res.set(j,s);
        }//將陣列中所有值相加
        String ans="0";
        while(length_y>0)
        {
          ans=add(ans,res.get(length_y-1),jishu);
          length_y--;
        }
        return ans;
    }

   public static String div(String x,String y,String jishu)
    {   if(compare(x,y)<0) return div(y,x,jishu);
        String ans="0";
        String Y=y;//儲存除數
        while(compare(x,y)>0)//x為每次剩餘部分的值 當剩餘部分大於y表示任需要除
        {
            int len=x.length()-y.length();//x比y多多少位
            while(x.length()>y.length())
            {
                y=y+"0";//例如x=789 y=35 x比y多一位 在y後面補0直到y與x位數相同
            }
            if(compare(x,y)<0) {
                y=y.substring(0,y.length()-1);//如果補0後位數相同但y大於x 則減去一個0
                len=len-1;
            }
            StringBuilder temp=new StringBuilder();
            for(int i=9;i>0;i--)//獲取結果的最高位
            {
                String mul = mul(String.valueOf(i), y, jishu);
                if(compare(mul,x)<=0){
                    temp.append(i);
                    for(int j=1;j<=len;j++)//前面補了多少零就表示需要新增多少0 x=789 y=35 補了一個0 最高位為2 再添上一個0 即一部分結果為20
                    {
                       temp.append("0");
                    }
                    ans=add(temp.toString(),ans,jishu);//20為一部分結果
                    x= sub(x, mul, jishu);//x=x減去已經取走的部分
                    y=Y;//y設為初始的y
                    break;
                }
            }
        }
        return ans+"   "+x;
    }

    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        System.out.println("please input first number: ");
        String x = scanner.next();
        System.out.println("please input second number: ");
        String y=scanner.next();
        System.out.println("please input jishu");
        String jishu = scanner.next();
        System.out.println("the add result: "+add(x,y,jishu));
        System.out.println("the sub result: "+sub(x,y,jishu));
        System.out.println("the mul result: "+mul(x,y,jishu));
        System.out.println("the div result: "+div(x,y,jishu));
    }
}

2021-11-13 21:51:53 星期六: