本程序涉及到的算法:任意进制转换成十进制计算用按权展开。这是一个公理,无需证明,可以直接拿来使用。
采取两种解题的思路:
方案一:先不予考虑小数点的存在,当做纯整数来处理。计算出结果后再对小数点进行单独处理:把计算结果除以R的m次方(其中m为小数点后面保留的位数)。
举个简单的例子:
(12.12)3这是三进制下的一个数据:
按照方案一怎么处理呢???
1212 按权展开后 再除以3的平方即可。
以下是方案一代码的展示:
/**
*任意R进制转换成十进制的图形界面
思路:先不考虑小数点 如:(121.2)3--->1212转换成十进制后再除以3的一次方(判断小数点后面的位数)
当成纯整数处理后,从右向左算,因为R的i次方越来越大。
*/
import java.util.Scanner;
public class TryR2D
{
public static void main(String[] args)
{
String base = "0123456789ABCDEF";
Scanner sc = new Scanner(System.in);
System.out.println("----------------------任意的R进制转换成十进制的命令行界面计算----------------------");
System.out.print("请输入需要转换的进制数:");
int r = sc.nextInt();
System.out.print("请输入" + r + "进制的数:");
//因为接收的数据可能是浮点数,所以我们用字符串来接收数据。
String msg = sc.next();
System.out.print(r + "进制的数" + msg +"转换为十进制的数:");
//在这里我们需要将字符装换成数据,如果是a或者A对应的是10,我们定义一个base。
//找到所在字符对应的下标即可。indexOf
int x = 0; //保留最终的结果
int temp = 1; //记录R的i次方,初始值为1
for(int i = msg.length() - 1; i >= 0; i--)
{
//接收字符
char ch = msg.charAt(i);
//出现小写字母时需要转换成大写字母
if(ch >= 'a' && ch <= 'f')
{
ch = (char)(ch - ('a'-'A'));
}
//扫描时如果遇到小数点,我们计算时暂时先忽略
if(ch == '.')
{
continue;//跳过本轮的循环,下面的代码不予执行。
}
//按权展开:需要x(保留最终的结果),temp(记录R的i次方)
x = x + base.indexOf(ch) * temp;
temp = temp * r;
}
//对小数点后面的位数进行处理:除以r的m次方。
//如果没有小数点
if(msg.indexOf('.') == -1)
{
System.out.print(x);
}
//如果有小数点
else
{
int m = msg.length() - 1 - msg.indexOf('.'); //举:3.123---> 5 -1 -1 = 3 小数点后面确实保留了三位
temp = 1; //经过上述的循环后temp值发生了改变,下面还需要再使用,重新赋值为1
for(int i = 0; i < m; i++)
{
temp = temp * r;
}
//循环结束最终的temp值为R的m次方
System.out.print(x * 1.0 / temp);
}
System.out.println();
}
}
方案二:找出小数点所在的下标位置,使用String类中的indexOf方法即可。
这样一个数据就被拆分成了两段:前面一段和后面一段,分别按权展开进行计算。注意此时的位权前后不一样哈。
以下是方案二代码的展示:
/**
*任意R进制的数转换成十进制的数
思路:找出小数点所在的位置(下标),然后前面一段后面一段单独进行按权展开计算处理。
*/
import java.util.Scanner;
public class TryR2D02
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String base = "0123456789ABCDEF"; //用于位权的计算:如果是A--->10
//输出一些提示性的语句
System.out.println("----------------------任意的R进制转换成十进制的命令行界面计算----------------------");
System.out.print("请输入需要转换的进制数:");
int r = sc.nextInt();
System.out.print("请输入" + r + "进制的数:");
String str = sc.next();//读取r进制范围内的那个数
System.out.print(r + "进制的数" + str +"转换为十进制的数:");
//找出小数点所在的下标
int index = str.indexOf('.');//index的值可能为-1
if(index == -1)//数据中没有小数点,纯整数,依旧采用从右往左算
{
int x = 0; //保留最终的数据结果
int temp = 1; //记录R的多少次方,初始值为1
for(int i = str.length() - 1; i >= 0 ; i--)
{
//接收字符
char ch = str.charAt(i);
//因为我们的base库中是大写的英文字母,所以我们需要将小写转换成大写字母
if(ch > 'a' && ch < 'f')
{
ch = (char)(ch - ('a' - 'A'));
}
//字符转换成数据,bas库体现出来的好处:通过字符所在的下标来参与计算
x = x + base.indexOf(ch) * temp;
temp = temp * r;
}
System.out.print(x);
}
else//数据中如果有小数点,那么以小数点为基准,前面一段后面一段分别用按权展开进行计算。
{
int q1 = 0;//保留小数点前面的计算结果
double q2 = 0;//保留小数点后面的计算结果
int t1 = 1; //小数点前面的位权
double t2 = Math.pow(r,-1); //小数点后面的位权(浮点数)
for(int i = index -1; i>=0; i--)//小数点前面一段的计算
{
//接收字符
char zf = str.charAt(i);
//小写字母转换成大写字母
if(zf >= 'a' && zf <= 'f')
{
zf = (char)(zf - ('a' - 'A'));
}
q1 = q1 + base.indexOf(zf) * t1;
t1 = t1 * r;
}
for(int i = index + 1; i <= str.length() - 1; i++)//小数点后面一段的计算
{
//接收字符
char nzf = str.charAt(i);
//小写字母转换成大写字母
if(nzf >= 'a' && nzf <= 'f')
{
nzf = (char)(nzf - ('a' - 'A'));
}
q2 = q2 + base.indexOf(nzf) * t2;
t2 = t2 * Math.pow(r,-1);
}
double sum = q1 + q2; //两段的总和
System.out.print(sum);
}
System.out.println();
}
}
进行了多组不同数据的测试,发现两种代码的展示结果一样。
最后进行简单总结:
两种设计的解决方案都可以,各有各的特色。方案一:先不需要考虑小数点,直接按权计算,再除。方案二:考虑小数点的位置后,进行了拆分。分为两段处理,要注意的是后面一段的数据保留为浮点数哈。同时里面可能涉及到小数点不存在的问题,需要单独处理,把逻辑思路想明白后写出来也不是很困难的。最后个人推荐方案一:总的来说方案一代码长度较短,设计比较新颖。方案二因为进行了拆分,需要多次接收字符,小写字母转换成大写字母,然后再分别计算,求和。类似的代码多次使用。方案一呢只使用了一次,最后通过除对小数点的问题进行了很好的处理。
但此程序还有不足的地方:没有进行数据的校验。比如2进制不能出现3,如果出现此类非法数据,使用该程序任然能参与计算,但是违背了我们的理论知识。感兴趣的朋友可以自行修改完善,本文只是个人的一点意见,仅大家参考和学习,感谢大家的喜欢和支持!