一:题目
输入整数a和b(
0<=a<=
3000,
1<=b<=
3000),输出a/
b的循环小数表示以及循环节长度。
例如,a=
5,b=
43,小数表示为0.(
116279069767441860465),循环字节长度为21
当循环节长度超过50时,后面使用...代替,不进行输出后面部分
(一)样例输入
76 25
5 43
1 397
(二)样例输出
76/
25 =
3.04(
0)
1 = number of digits
in repeating cycle
5/
43 =
0.(
116279069767441860465)
21 = number of digits
in repeating cycle
1/
397 =
0.(
00251889168765743073047858942065491183879093198992...)
99 = number of digits
in repeating cycle
二:题目分析
(一)余数用作判断循环节的依据:(循环节长度大小不会超过余数大小,原因如下:)
1/
6-->
10/
6=
1...
4
4/
6-->
40/
6=
6...4出现两次4,所以一定会出现循环节
4/
6-->
40/
6=
6...4出现三次4,所以循环节就在二三次之间(即商6)
所以用一个数组记录余数,大小不会超过除数大小
(二)同时也要记录商,用于记录循环节
若是除数为P,则余数为0->P-1;所以在P次之间一定会出现两个相同余数 //(一中原因)
-->一定会出现循环节
所以我们再记录一次余数,当出现某个余数出现为3次,那么循环节在两个余数位置中间
由于商数组和余数数组对应,所以可以轻松找到循环节
(三)商数组和余数数组大小
余数数组大小应该为除数大小 //余数只需要除数大小,用于记录余数出现次数
商数组大小应该为除数大小的两倍 //商用于记录对应余数中的商值,由于每一个余数必须出现3次,所以我们记录的商必须足够长,足以支持余数次数到达3
例:
其中0<=a<=
3000,
1<=b<=
3000--->
所以余数数组不会超过3000 商数组大小不超过6000
注:上面的商和余数数组只记录小数点后的值,不记录整数值
三:代码分析(使用76/25 ,1/6 ,5/43分析)
(一)处理整数部分:只剩下会出现小数部分的被除数进行下一步处理
//开始处理数据
//1.获取整数
//先记录整数:可以在记录时直接输出,节省篇幅
printf(
"%d/%d = ", a, b);
if (!(a /
b))
printf("0");
else
while (a /
b)
{
printf("%d", a /
b);
a %=
b;
}
printf(".");
(1)76/25
76/
25=
3...
1
代码输出76/25 = 3.
(2)1/6
直接为小数,所以按照代码输出1/6 = 0.
(3)5/43
直接为小数,所以按照代码输出5/43 = 0.
(二)获取商数组和余数数组
//2.开始记录商和余数
i =
0;
while (
1)
//例如:1/6
{
//记录商和余数
res[i] = a * 10 / b; //10/6=1 //1.记录商
rem[a * 10 % b]++; //10%6=4 //2.记录对应余数位置出现次数
//注意两次和三次都是只记录一次即可
if (rem[a * 10 % b] == 2&&!two_flag) //3.若是出现两次,则开始进行记录 只记录第一个出现两次的余数
{
r_s =
i;
two_flag =
1;
}
if (rem[a * 10 % b] == 3) //4.若是出现3次,则确定了循环节位置,直接跳出
{
r_e =
i;
break;
}
//处理被除数
a = a *
10 % b;
//a = 4
i++
;
}
(1)76/25
10/
25=
0...
10 0 1 第一个为商下标,第二个为余数次数
100/
25=
4...
0 1 1
0/
25=
0...
0 2 2 余数出现两次时的商0和出现一次时的商4不一致
0/
25=
0...
0 3 3
res = {
0 4 0 0}
rem = {
3 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0}
(2)1/6
10/
6=
1...
4 0 1 第一个为商下标,第二个为余数次数
40/
6=
6...
4 1 2 余数出现两次时的商6和出现一次时的商1不一致
40/
6=
6...
4 2 3
res = {
1 6 6 }
rem = {
0 0 0 0 3 0 }
(3)5/43
50/
43=
1...
7 0 1
70/
43=
1...
27
...
.....=
1...
7 21 2 余数出现两次时的商和出现一次时的商一致
...
.....=
1...
7 42 3
(三):进行数据输出
注意记录数据时要区分0.
1(
6)
3.04(
0) 和0.(
11....)
不同之处在于循环节是不是从小数第一位开始
处理原则在于看1,2两次余数相同时,商是否一致(上面案例)
int rep_count = r_s;
if (res[r_s] != res[2 * r_s - r_e]) //若是余数第一次和第二次对应的商值不一样,则加一
rep_count++;
for (j =
0; j <rep_count ;j++)
//注意,先看下面注释,可以知道,真正循环节结束在我们获取的第二个相同余数位置-->即r_s
{
if (j ==
2 * r_s - r_e && rep_count==r_s)
//注意这里:不是j-r_s
printf(
"(");
else if (j ==
2 * r_s - r_e+
1&&rep_count==r_s+
1)
//遇到循环节不是从小数点后开始,则向后一位
printf(
"(");
printf("%d", res[j]);
if (j +r_e-
2*r_s ==
49)
//不是j-r_s -->因为我们虽然确定r_s到r_e时一个循环节,但是r_s是第二个相同余数开始,r_e是第三个余数开始
{
//4 4 4--->r_s是第二个开始,r_e是第三个开始,但是真的循环节是从第一个4到第二个4
printf(
"...");
break;
}
}
printf(")\n");
printf(" %d = number of digits in repeating cycle\n", r_e - r_s);
四:代码实现
void test33()
{
int a, b;
int zs[
4];
//存放整数,例如结果10.13161616,这里用于存放10
//由于程序变更,后面没有用到zs,但是为了便于理解,留在这
int res[MAX_REP];
//存放商
int rem[MAX_REP];
//存放余数
int two_flag;
//注意两次和三次都是只记录一次即可,但是由于三次直接break,所以不做标志
int i, j;
int r_s, r_e;
//循环节开始,循环节结束
FILE* fi = freopen(
"data2.in",
"r", stdin);
freopen("data2.out",
"w", stdout);
while (!
feof(fi))
{
scanf("%d", &
a);
scanf("%d", &
b);
memset(zs, 0,
sizeof(zs));
memset(res, 0,
sizeof(res));
memset(rem, 0,
sizeof(rem));
two_flag =
0;
//开始处理数据
//1.获取整数
//先记录整数:可以在记录时直接输出,节省篇幅
printf(
"%d/%d = ", a, b);
if (!(a /
b))
printf("0");
else
while (a /
b)
{
printf("%d", a /
b);
a %=
b;
}
printf(".");
//2.开始记录商和余数
i =
0;
while (
1)
//例如:1/6
{
//记录商和余数
res[i] = a *
10 / b;
//10/6=1
rem[a *
10 % b]++;
//10%6=4
//注意两次和三次都是只记录一次即可
if (rem[a *
10 % b] ==
2&&!two_flag)
//若是出现两次,则开始进行记录
{
r_s =
i;
two_flag =
1;
}
if (rem[a *
10 % b] ==
3)
{
r_e =
i;
break;
}
//处理被除数
a = a *
10 % b;
//a = 4
i++
;
}
//开始记录数据
//注意记录数据时要区分0.1(6) 3.04(0) 和0.(11....)
//不同之处在于循环节是不是从小数第一位开始
//处理原则在于看1,2两次余数相同时,商是否一致
int rep_count =
r_s;
if (res[r_s] != res[
2 * r_s -
r_e])
rep_count++
;
for (j =
0; j <rep_count ;j++)
//注意,先看下面注释,可以知道,真正循环节结束在我们获取的第二个相同余数位置-->即r_s
{
if (j ==
2 * r_s - r_e && rep_count==r_s)
//注意这里:不是j-r_s
printf(
"(");
else if (j ==
2 * r_s - r_e+
1&&rep_count==r_s+
1)
//遇到循环节不是从小数点后开始,则向后一位
printf(
"(");
printf("%d", res[j]);
if (j +r_e-
2*r_s ==
49)
//不是j-r_s -->因为我们虽然确定r_s到r_e时一个循环节,但是r_s是第二个相同余数开始,r_e是第三个余数开始
{
//4 4 4--->r_s是第二个开始,r_e是第三个开始,但是真的循环节是从第一个4到第二个4
printf(
"...");
break;
}
}
printf(")\n");
printf(" %d = number of digits in repeating cycle\n", r_e -
r_s);
}
freopen("CON",
"r", stdin);
freopen("CON",
"w", stdout);
}
转载于:https://www.cnblogs.com/ssyfj/p/10818986.html
相关资源:Laravel开发-number2word