这个程序为《数学之美系列程序》之一。
这个问题是:找出所有n位数中的循环数。
一个n位数中的循环数是指该数乘以1到n之后,每位数字顺序发生移位,可以是移动若干位。
例如:142857是一个6位数的循环数,满足以下条件:
142857*1=142857
142857*2=285714
142857*3=428571
142857*4=571428
142857*5=714285
142857*6=857142
经过试算,这样的数并不好找,1到6位数中只有这一个。
给出的程序是按照自顶向下逐步细化的编程方法编写的顺序程序。对于程序员来说这样的编程训练是必要的,毕竟编写顺序程序是常有的事情。
程序如下:
/* 找出所有n位数中的循环数,该数乘以1到n的数后,每位数字顺序发生移位,可以是移动若干位。
*
* 例如:142857是一个6位数的循环数,满足以下条件:
* 142857*1=142857
* 142857*2=285714
* 142857*3=428571
* 142857*4=571428
* 142857*5=714285
* 142857*6=857142
*
*/
#include <stdio.h>
// 判定n位数v乘以r是否为循环数,变量gethighdigit用于获取v的最高位
int isCycle(int v, int n, int r, int gethighdigit)
{
int t, i, highdigit;
t = v * r;
// 乘积有进位则不是循环数
if(t / gethighdigit / 10 > 0)
return 0;
// 把最高位循环移位到最低位
for(i=1; i<=n; i++) {
// 取出最高位
highdigit = t / gethighdigit;
// 计算循环移位结果
t = t % gethighdigit * 10 + highdigit;
// 循环移位后,某个数是原数的循环移位结果,则该数乘以r为循环数
if(t == v)
return 1;
}
// 所有的循环移位都不是循环数,则原数不是循环数
return 0;
}
// 判定n位数v是否为循环数
int isCycleNumber(int v, int n)
{
int i, gethighdigit=1;
// 计算用于取最高位的数
for(i=1; i<n; i++)
gethighdigit *= 10;
// 乘以2到n的数,有一个不是循环数则该数不是循环数
for(i=2; i<=n; i++)
if(!isCycle(v, n, i, gethighdigit))
return 0;
// 乘以2到n的数,都是循环数,则该数是循环数
return 1;
}
int main(void)
{
int n, start=1, end=9, i, j;
// 输入n
scanf("%d", &n);
// 计算n位数的最小值start和最大值end
for(i=1; i<n; i++) {
start *= 10;
end *= 10;
end += 9;
}
// 对所有的n位数,判定该数是否为循环数,若为循环数则输出
for(i=start; i<=end; i++)
if(isCycleNumber(i, n)) {
printf("%d\n", i);
for(j=1; j<=n; j++)
printf("%d*%d=%d\n", i, j, i*j);
}
return 0;
}
输入6时,程序执行结果如下:
6
142857
142857*1=142857
142857*2=285714
142857*3=428571
142857*4=571428
142857*5=714285
142857*6=857142