《Java實現大數運算--成電信軟信安數學實驗一》
阿新 • • 發佈:2022-02-19
大數運算介紹
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 星期六: