用java實現十進位與二進位小數的互轉機制
本篇部落客要講述用java實現十進位與二進位小數的互轉(不調用java內建的函數)。後期可能會用MATLAB實現,因為我們資訊安全的一個實驗是要求用MATLAB實現的。 要求
資訊安全課程的一個實驗要求
1、 編寫程式實現十進位小數x=0.7 的二進位轉換,並分析其誤差(即重新將二進位小數轉成十進位小數,和原十進位小數進行比較。)
2、編程實現十進位數 x=5.9的二進位轉換。 思路
第二小題的思路,就是將十進位分開為整數部分和小數部分分來實現。 實現
MATLA實現
%%clearclcn=0.7;m=20;%保留10位小數%將十進位乘以2用floor取整,接著用其餘數進行迴圈操作d=char(mod(floor(n*2.^(1:m)),2)+'0');%char函數建立一個字元矩陣d1=[d(1:end-m),'.',d(end-m+1:end)]%顯示二進位轉換小數f=d-'0';f1=sum(f./(2.^(1:m))) %% 二進位轉換十進位error = n-f1
java語言實現
執行環境:JDK1.8,IntelliJ IDEA 2017.3.4 x64。
import static java.lang.System.out;/** * 實現二進位與十進位的互換 * @author Canlong * @time 2018/4/13 */public class Test3 { /** * 1、 編寫程式實現十進位小數x=0.7 的二進位轉換,並分析其誤差(即重新將二進位小數轉成十進位小數,和原十進位小數進行比較。) 2、編程實現十進位數 x=5.9的二進位轉換。 * @param args */ public static void main(String[] args){ //要轉化的十進位小數 double x = 0.7; //將十進位小數轉化為二進位 String binXStr = decXiao2Bin(x); //將二進位小數轉化為十進位 double decX = bin2DecXiao(binXStr); out.println("誤差為:"+(x-decX)); //將十進位數轉化為二進位 double decX1 = 5.9; int decInt = (int) Math.floor(decX1); double decXiao = decX1-decInt; String binInt = decInt2Bin(decInt); String binX = decXiao2Bin(decXiao); out.println("5對應的二進位為:"+binInt); out.println("5.9對應的二進位為:"+binInt+"."+binX); } //將十進位整數轉換為二進位 public static String decInt2Bin(int decInt){ int index = 0; int rem = 1; String binStr=""; while(decInt!=1){ rem = decInt%2; decInt = decInt/2; binStr += Integer.toString(rem); if(decInt == 1){ binStr+=Integer.toString(decInt); } } return binStr; } /** * 將十進位小數轉化為二進位 */ public static String decXiao2Bin(double x){ //精確位元 int accurate = 100; int[] binX = new int[accurate]; String binXSB=""; double x1 = x; double x2=0; for(int i=0;i<binX.length;i++){ x2 = x1+x1; x1 =Math.floor(x2); binX[i]=(int)x1; x1=x2-x1; binXSB += Integer.toString(binX[i]); } String binXStr = binXSB.toString(); out.println(x+"的近似位元為(精確到小數點後"+accurate+"位):"+binXStr); return binXStr; } /** * 將二進位小數轉化為十進位 * @param binXStr 二進位小數 * @return 十進位小數 */ public static double bin2DecXiao(String binXStr){ double decX = 0.0; //位元 int k =0; for(int i=0;i<binXStr.length();i++){ int exp = binXStr.charAt(i)-'0'; exp = -(i+1)*exp; if(exp!=0) { decX += Math.pow(2, exp); } } out.println("二進位小數為;"+binXStr+"。\r\n其對應的十進位為:"+decX); return decX; }}
結果
誤差分析:
測試了多次,java代碼和matlab中將十進位小數轉化為二進位小數,如果使用double來儲存,最多隻能轉化到二進位到小數點後53位,再往後的數都為0。而且由於double類型的數值,java只能儲存到小數點後16位,只要在這個範圍內,利用以上的轉化代碼,產生的誤差都為0。至於為什麼利用數組儲存二進位也只能儲存到位元後53位,該原因還有待探索。初步懷疑由於十進位小數轉化為二進位小數時不斷減去整數部分,最終導致小數部分很少,即使進行了多次加倍,仍然無法達到1或者是電腦儲存某個小數最多的二進位小數就是小數點後53位。
後來經過輸出每一步的轉化的十進位小數,發現每次都在第50步左右,十進位小數就變成了0.5,所以原因應該是只要是十進位小數為小數點16位以內,都可以通過50次加倍(加倍前去掉整數部分)變成0。 總結
總的來說,這個實現起來並沒有太大難度,只是由於自己對於方法啟動並執行不熟悉,而導致自己寫了很多多餘的代碼的和浪費了很多時間才能把這個課堂實驗做完。下次有機會再完善一下。至於實現的原理,也在下次有機會的時候再說。其實java內部有函數實現十進位和二進位的互換的,但是經過自己把二進位和十進位的轉換從原理層級上去實現後,能夠鍛煉了自己的思維能力。經過這次的實踐,發現自己對於二進位與十進位轉化的理論還沒有太熟悉,java實現起來也效率極低。不過經過這次實踐,我對這個轉換的理論和實踐部分的理解都加深了不少,後面會繼續學習。