将分数表示为任意进制的小数(一)

2014-11-24 02:30:40 · 作者: · 浏览: 4
最近在翻看一本数学分析教材中关于实数的基本理论的章节,其中对有理数的小数表示方法给出了严密的定义和详细的讨论。看后很有收获,然后突然就想到了这么个问题,如何编个程序将有理数的分数表示转换为小数表示,并且对于无限循环小数还要给出循环节来。
花了半天时间将程序写好调通。把程序放在这里做个记录。
首先我先写了个只能处理正的真分数的程序。这是最简单的情况。不用判断正负号,也不用考虑整数部分。虽然说是任意进制,但是程序只支持到36进制,如果需要更多进制,可以修改程序。
[cpp]
void properfrac2str(int numerator, int denominator, int radix, char str[], int strl)
{
const char table[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int *num_array;
int find_loop = 0;
int loop_from, loop_to;
int i = 0, j;
if(numerator == 0 || strl <= 1)
{
str[0] = 0;
return;
}
num_array = (int *) malloc(strl * sizeof(int));
num_array[0] = numerator;
for (i = 0; i < strl - 3; i++)
{
numerator *= radix;
str[i] = table[numerator / denominator];
numerator %= denominator;
if(numerator == 0)
{
str[i + 1] = 0;
break; //finish
}
num_array[i + 1] = numerator;
for(j = 0; j < i; j++)
{
if( numerator == num_array[j] ) // Recurring decimal
{
loop_from = j;
loop_to = i;
//printf("\nloop from %d to %d\n", loop_from, loop_to);
find_loop = 1;
break;
}
}
if(find_loop == 1)
{
str[loop_to + 2] = ']';
str[loop_to + 3] = 0;
for(j = loop_to; j >= loop_from; j --)
{
str[j + 1] = str[j];
}
str[loop_from] = '[';
break;
}
}
free(num_array);
}
一个简单的测试代码如下:
[cpp]
void properfrac2str(int numerator, int denominator, int radix, char str[], int strl);
int main()
{
char str[100];
properfrac2str(1, 71, 10, str, 99);
printf("0.%s\n", str);
return 0;
}
结果显示为: 0.[01408450704225352112676056338028169]
[] 内为循环小数的循环节。
然后是处理任意分数,无非就是将分数分解为整数部分和真分数部分,还要判断下正负号。难度不大,下面是代码。
[cpp]
int frac2str(int numerator, int denominator, int radix, char *str, int strl)
{
char strIntPart[33];
int l;
int intPart;
int sign = 1;
if(denominator == 0)
{
fprintf(stderr, "ERROR: denominator is 0\n");
return -2;
}
if( (numerator ^ denominator) < 0)
{
sign = -1;
numerator = abs(numerator);
denominator = abs(denominator);
}
// reduction of a fraction
l = gcd(numerator, denominator);
numerator /= l;
denominator /= l;
// seperate the fraction to an integer part and a proper fraction
intPart = numerator / denominator;
numerator = numerator % denominator;
itoa(intPart, strIntPart, radix);
strcat(strIntPart, ".");
l = strlen(strIntPart);
if(sign == -1)
{
str[0] = '-';
str ++;
strl --;
}
if(strl < l)
{
fprintf(stderr, "ERROR:string is too short to hold the result!\n");
return -1;
}
strcpy(str, strIntPart);
// printf("%s", str);
if(numerator != 0 && strl - l != 0)
{
properfrac2str(numerator, denominator, radix, str + l, strl - l);
}
return 0;
}
其中用到了求两个整数的最大公因数的函数,代码如下:
[cpp]
int gcd(int a, int b)
{
int temp;
while(a != 0)
{
temp