这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战
原理就跟我们平常手动的去16进制转10进制一样,是通过最常用的按权展开的方法,即位权,那么为了将输入的16进制分开,方便我们进行每位按权去求10进制,我们可以用一个字符数组通过下标来实现这种需要。
想法:
通过按权展开的方法: (BC)H=11x16^1 + 12x16^0
那么首先了解下什么是位权:
位权:在数制中每一固定位置对应的单位值称为位权。即比如我们日常生活中经常使用的十进制举例。
十进制:110D(D 结尾代表十进制,B 结尾代表二进制,O 结尾代表八进制,H 结尾代表十进制) 那么我们可以看到 123D 的个位就是 0,又因为它是十进制,所以个位的位权为10的0次方,即10^0=1; 同理,十位上的位权则为10的1次方,即10^1=10;百位上的位权就可以是10的2次方,即10^2=100; 最后我们按权相加起来,即 10^21+10^12+10^0*3=123。按权展开很神奇吧。 那么怎么判断位权的基数呢,就好比将123D看作在一个数轴上,个位为原点,x=0,向左依次递增,向右依次递减。若基数为 10,则 每位的位权就是 10^x 。
我们就可以通过判断每位相对于小数点的位置就可以分辨出整数部分和小数部分。
步骤:
- 用字符数组来放16进制
- 将数组元素逆序排放
- 将数组元素的下标当做16进制的权
- 将字符转换成数字 * 16的权
代码实现
float fun(int n) //递归函数实现16的N次方
{
if(n==0)
return 1;
else
return 16*fun(n-1);
}
void main()
{
char s[20],*s1=s,*s2=s,*s3=s,t;
int num;
float sum=0.0;
gets(s);
while(*s1) s1++;
for(num=s1---s;s2<s1;s2++,s1--) //将数组元素逆序排放
t=*s2,*s2=*s1,*s1=t;//数组元素的下标当做16进制的权
while(*s3)
{
if(*s3=='.')
break;
s3++;
}
for(s1=s;s1<s+num;s1++)
{
if(s1-s3<0&&*s3=='.') //求小数部分,*s3='.',说明有小数
{
if(*s1>=48&&*s1<=57) //根据小数点的下标确定16的权
sum=sum+(*s1-48)/fun(s3-s1); //将字符转换成数字 * 16的权
else if(*s1>='A'&&*s1<='Z')
sum=sum+(*s1-55)/fun(s3-s1);
else if (*s1>='a'&&*s1<='z')
sum=sum+(*s1-87)/fun(s3-s1);
}
else if(*s3=='.') //求整数部分,*s3='.',说明有小数
{
if(*s1>=48&&*s1<=57) //根据小数点的下标确定16的权
sum=sum+(*s1-48)*fun(s1-s3-1); //将字符转换成数字 * 16的权
else if(*s1>='A'&&*s1<='Z')
sum=sum+(*s1-55)*fun(s1-s3-1);
else if (*s1>='a'&&*s1<='z')
sum=sum+(*s1-87)*fun(s1-s3-1);
}
else
{
if(*s1>=48 && *s1<=57) //将字符转换成数字 * 16的权
sum=sum+(*s1-48)*fun(s1-s);
else if(*s1>='A'&&*s1<='Z')
sum=sum+(*s1-55)*fun(s1-s);
else if (*s1>='a'&&*s1<='z')
sum=sum+(*s1-87)*fun(s1-s);
}
}
printf("%f",sum);
}