(一)问题描述
使用数组精确计算 M/N (0<M<N<100)的值。如果 M/N 是无限循环小数,则计算输出他的第一个循环节,并输出循环节的起止位置。
(二)算法分析
两整数相除时,当出现重复的余数时说明循环节出现了。且每个余数必定小于 N,故最多除 N 次就出现循环节,否则就是有限小数的情况。
因此在设计程序时,定义两个数组分别存放每次相除得到的商和余数,若出现余数为0,则说明结果是有限小数,无循环节,否则就判断此余数在前面是否出现过,以确定循环节是否出现。
(三)源码展示
#include <stdio.h>
#define MAX 100 //最多可以精确到小数点后100位
int main(void)
{
int m, n, i = 0, j, beg, end;
int flag = 0; //表示结果是否是无限循环小数
int a[MAX], b[MAX]; //分别存放相处过程中的商和余数
printf("请输入m, n的值:");
scanf("%d%d", &m, &n);
b[i] = m;
a[i] = m * 10 / n;
while(i < MAX){ //在超过最大位数之前
b[i] = b[i - 1] * 10 % n;
if(b[i] == 0){ //可以整除
beg = 0;
end = i;
flag = 1;
break;
}
a[i] = b[i] * 10 / n;
for(j = i - 1; j >= 0; j--){ //判断前面有无此余数,有则说明循环节出现
if(b[j] == b[i]){
beg = j;
end = i;
break;
}
}
if(j >= 0) break; //找到了相同的余数,循环节出现了
i++;
}
if(flag){
printf("m/n的结果是有限小数 0.");
for(j = beg; j < end; j++){
printf("%d", a[j]);
}
}
else{
printf("m/n的结果是无限循环小数 0.");
for(j = 0; j < end; j++){
printf("%d", a[j]);
}
printf("...\n");
printf("其循环节是从第 %d 位开始,循环节是:", beg + 1);
for(j = beg; j < end; j++){
printf("%d", a[j]);
}
}
}
(四)程序说明
当 M/N 是有限小数时,beg 为0,end 表示小时小数点后的数字位数;当 M/N 是无限循环小数时,beg 表示循环节开始的位置,end 表示循环节结束的位置。
(五)心得思考
本实例给出一种思想,用数组记录数据,数据的每位数字放到数组的一个元素中。如果当一个特别大的整数,赋予一个长整型变量可能会产生溢出,就可以考虑将其放入一个数组中,其每位数字是数组的一个元素。