用java实现十进制与二进制小数的互转机制
本篇博客主要讲述用java实现十进制与二进制小数的互转(不调用java自带的函数)。后期可能会用MATLAB实现,因为我们信息安全的一个实验是要求用MATLAB实现的。
要求
信息安全课程的一个实验要求
1、 编写程序实现十进制小数x=0.7 的二进制转换,并分析其误差(即重新将二进制小数转成十进制小数,和原十进制小数进行比较。)
2、编程实现十进制数 x=5.9的二进制转换。
思路
第二小题的思路,就是将十进制分开为整数部分和小数部分分来实现。
实现
MATLA实现
%%
clear
clc
n=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实现起来也效率极低。不过经过这次实践,我对这个转换的理论和实践部分的理解都加深了不少,后面会继续学习。