1.进制转换
转换方法:1)整数部分——辗转除r取余直到商为0,将余数作反向排列;
2)小数部分——反复乘r取整数部分,直到小数部分为0(若不能为0,则取整数个数最多5位),将各次所取整数正向排列
由于我们只有10个数字和26个字母,所以理论上我们可以实现36进制的转换。首先我们需要一个将数字转换为字符的函数(因为大于十进制的进制会出现英语字母,所以我们输出的结果应为一个字符串),在数字小于10的时候,直接转换为对应的数字字符,当数字大于或等于10的时候,将其按照 10 ->A ,11 -> B , 12 -> C ........ 35 -> Z 的方式转换,如下
char digit_to_char(int value)
{
return (value < 10) ? ('0' + value) : ('A' + (value - 10));
/*
digit_to_char 将数值位映射成单个字符:若 value 在[0,9],返回 '0'+value 得到 '0' 到 '9';否则返回 'A'+(value-10),即把 10↦'A'、11↦'B' …… 35↦'Z'
*/
}现在我们实现进制转换的函数,该函数接受一个浮点数(待转换的数)和一个整数(需要转换的进制),返回一个字符串(C语言风格的字符串实际上是一个字符数组char str[] 所以我们的返回值应为一个字符类型的指针char*)在函数内部,我们首先要判断需要转换的进制是否在[2,36]内,如果不在,直接返回NULL 。然后为了方便,我们需要对带转换的数取绝对值,然后在组合结果字符串的是否再判断是否要添加负号,所以我们在取绝对值之前要先用一个变量来存储是否需要负号
bool is_negative = dec < 0;//记录符号位
double abs_dec = fabs(dec);//取绝对值进行转换接下来就是提取整数部分和小数部分
long long int_part = (long long)abs_dec;//整数部分
double frac_part = abs_dec - (double)int_part;//小数部分然后我们就需要两个数组来分别存储整数和小数的转换结果,这里整数部分数组长度可以稍微大一点,小数部分根据题目要求直接取5,同时为了节省结果字符串的的内存,我们可以用两个变量来分别记录两个数组的实际使用长度
char res_int[128];//存储整数部分转换结果的字符数组
char res_frac[5];//存储小数部分转换结果的字符数组
int size_int = 0;
int size_frac = 0;接下来就是转换的过程,直接根据进制转换的方法实现即可
if (int_part == 0)
{
res_int[size_int] = '0'; //处理整数部分为 0 的特殊情况
size_int++;
}
else
{
while (int_part > 0 && size_int < (int)(sizeof(res_int)))//转换整数部分
{
int digit = (int)(int_part % r);
res_int[size_int] = digit_to_char(digit);
size_int++;
int_part /= r;
}
}
while (frac_part > 0.0 && size_frac < (int)(sizeof(res_frac)))//转换小数部分
{
frac_part *= r;
int temp = (int)frac_part;
res_frac[size_frac]= digit_to_char(temp);
size_frac++;
frac_part -= temp;
if (fabs(frac_part) < 1e-12)
{
frac_part = 0.0;
}
}在转换完之后,我们就要拼接结果字符串,在那之前,我们可以简单的判断一下传入的数是否有小数部分
bool needs_decimal = size_frac > 0;//判断是否需要小数点接下来我们申请结果字符串的内存,内存大小可以这样计算:
1.如果为负数,需要用一个单位内存来存储负号
2.整数部分的结果
3.如果为小数,需要一个单位内存来存储小数点
4.小数部分的结果
5.由于我们想要得到一个字符串,所以还要在结尾加上一个'\0'标志字符串的结尾
基于以上要点,我们计算所需的总内存然后申请
size_t total_len = (is_negative ? 1 : 0) + size_int + (needs_decimal ? 1 + size_frac : 0) + 1;//计算总长度,包括符号位、小数点和终止符
char *result = (char *)malloc(total_len);//分配结果字符串的内存然后就是将以上内容拼接进结果字符串
int index = 0;//结果字符串的当前索引
if (is_negative)//添加符号位
{
result[index] = '-';
index++;
}
for (int i = size_int - 1; i >= 0; i--)//添加整数部分(逆序)
{
result[index] = res_int[i];
index++;
}
if (needs_decimal)//添加小数点和小数部分
{
result[index] = '.';
index++;
for (int i = 0; i < size_frac; i++)
{
result[index] = res_frac[i];
index++;
}
}
result[index] = '\0';//添加字符串终止符最后给出完整代码
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
char digit_to_char(int value)
{
return (value < 10) ? ('0' + value) : ('A' + (value - 10));
/*
digit_to_char 将数值位映射成单个字符:若 value 在[0,9],返回 '0'+value 得到 '0' 到 '9';否则返回 'A'+(value-10),即把 10↦'A'、11↦'B' …… 35↦'Z'
*/
}
char *trans(double dec, int r)
{
if (r < 2 || r > 36)
{
return NULL;
} // 由于 digit_to_char 函数只能处理 0-35 的数值位,因此进制 r 必须在 [2,36) 范围内
bool is_negative = dec < 0;//记录符号位
double abs_dec = fabs(dec);//取绝对值进行转换
long long int_part = (long long)abs_dec;//整数部分
double frac_part = abs_dec - (double)int_part;//小数部分
char res_int[128];//存储整数部分转换结果的字符数组
char res_frac[5];//存储小数部分转换结果的字符数组
int size_int = 0;
int size_frac = 0;
if (int_part == 0)
{
res_int[size_int] = '0'; //处理整数部分为 0 的特殊情况
size_int++;
}
else
{
while (int_part > 0 && size_int < (int)(sizeof(res_int)))//转换整数部分
{
int digit = (int)(int_part % r);
res_int[size_int] = digit_to_char(digit);
size_int++;
int_part /= r;
}
}
while (frac_part > 0.0 && size_frac < (int)(sizeof(res_frac)))//转换小数部分
{
frac_part *= r;
int temp = (int)frac_part;
res_frac[size_frac]= digit_to_char(temp);
size_frac++;
frac_part -= temp;
if (fabs(frac_part) < 1e-12)
{
frac_part = 0.0;
}
}
bool needs_decimal = size_frac > 0;//判断是否需要小数点
size_t total_len = (is_negative ? 1 : 0) + size_int + (needs_decimal ? 1 + size_frac : 0) + 1;//计算总长度,包括符号位、小数点和终止符
char *result = (char *)malloc(total_len);//分配结果字符串的内存
int index = 0;//结果字符串的当前索引
if (is_negative)//添加符号位
{
result[index] = '-';
index++;
}
for (int i = size_int - 1; i >= 0; i--)//添加整数部分(逆序)
{
result[index] = res_int[i];
index++;
}
if (needs_decimal)//添加小数点和小数部分
{
result[index] = '.';
index++;
for (int i = 0; i < size_frac; i++)
{
result[index] = res_frac[i];
index++;
}
}
result[index] = '\0';//添加字符串终止符
return result;
}
int main()
{
double dec;
int r;
scanf("%lf", &dec);
scanf("%d", &r);
char *result = trans(dec, r);
if (!result)
{
printf("invalid input\n");
return 1;
}
printf("%s\n", result);
free(result);
result = NULL;
return 0;
}