最近在复习考研的c语言编程,对于我这种总是用C++刷题的突然一下不能用C++只能用C了还是有点难受,想要多练练。然后我就遇到了一道浮点数进制转换的题目,按理说是很简单的,但是小数部分的进制转换我却想了半天,发现必须要用字符串处理,不然会出现很多精度问题。然后我想百度看看别人的解决方法,结果找到的都是在线进制转换器= =,所以在这里记录一下我的方法。
#include<stdio.h>
#include<string.h>
#include<math.h>
char* hexConvert(char* num,int begin,int end)//将浮点数num从begin进制转化成end进制(36进制以内)
{
//先转化成十进制便于计算
double eps = 1e-8;//精度为1e-8,如果对精度要求高可以调小
int int_D = 0;//十进制整数部分
double dec_D = 0;//十进制小数部分
double indexf = 1.0 / double(begin);//小数部分相应位的权重
bool isInt = true;
for (int i = 0; i < strlen(num); i++)
{
if (num[i] == '.')//找到小数点,后面的是小数位
{
isInt = false;
continue;
}
if (isInt)//处理整数位
{
int_D *= begin;
if(num[i]>='0'&&num[i]<='9')
int_D += (num[i] - '0');
if (num[i] >= 'a' && num[i] <= 'z')
int_D += (num[i] - 'a' + 10);
}
else//处理小数位
{
if (num[i] >= '0' && num[i] <= '9')
dec_D += indexf * (num[i] - '0');
if (num[i] >= 'a' && num[i] <= 'z')
dec_D += indexf * (num[i] - 'a' + 10);
indexf /= double(begin);
}
}
//将转化好的十进制转化为目标进制
char* ans;//答案字符串
char int_T[1005], dec_T[1005];//目标进制的整数部分和小数部分
int int_T_index = 0, dec_T_index = 0;
int tmp;
while (int_D)//处理整数位
{
tmp = int_D % end;
if (tmp >= 0 && tmp <= 9)
int_T[int_T_index++] = '0' + tmp;
if (tmp >= 10 && tmp <= 35)
int_T[int_T_index++] = 'a' + tmp - 10;
int_D /= end;
}
int_T[int_T_index] = '\0';
ans = _strrev(int_T);//整数部分是先获取的低位后获取的高位,所以要反转,strrev函数被_strrev替代了
indexf = 1.0 / double(end);
while (fabs(dec_D)>=eps)//处理小数位,dec_D如果小于精度就默认为0,跳出循环,否则当作不为0,继续处理
{
tmp = int(dec_D / indexf);
if (tmp >= 0 && tmp <= 9)
dec_T[dec_T_index++] = '0' + tmp;
if (tmp >= 10 && tmp <= 35)
dec_T[dec_T_index++] = 'a' + tmp - 10;
dec_D -= tmp * indexf;
indexf /= end;
}
dec_T[dec_T_index] = '\0';
strcat(ans, ".");
strcat(ans, dec_T);
return ans;
}
123.456从7进制转18进制结果是3c.c7fc7fc
asdf.jklm从32进制转24进制结果是11j9n.ehf3e
测试了几条结果,与在线进制转换器的结果都是一致的。