[算法浅析] 计算循环节

来源:互联网 发布:淘宝广州模特招聘骗局 编辑:程序博客网 时间:2024/06/13 00:21

整体的思路来自于这篇文章:http://hi.baidu.com/chu2rikka/item/59ff471961814ae45f53b1cf
#include<iostream>
#include<map>
#include<cmath>
using namespace std;

int gcd(int x, int y)
{
    return y == 0 ? x : gcd(y, x % y);
}

int main()
{
    int x, y, tmp;
    while(~scanf("%d%d", &x, &y))
    {
        int div = gcd(x, y);
        x /= div; // 例如4/24要转化成1/6,不然的话会对后面分母计算2与5的因子数有干扰
        y /= div;
        int num = x % y;
        printf("%d.", x / y); // 首先输出整数部分
        if(x % y == 0) // 若是4/2则没必要计算,直接输出结果
        {
            printf("0\n");
            continue;
        }
        int aa, bb = 0, tmp = y;
        aa = (int)log2((tmp & (-tmp))); // 计算分母中质因数2的个数,这里用了个小技巧
        while(tmp % 5 == 0) // 计算分母中质因数5的个数
        {
            bb++;
            tmp /= 5;
        }
        aa = aa > bb ? aa : bb; // 质因数2和5的数量谁多,循环节就从几位开始,例如45/56,aa=3
        while(aa--) // 前几位小数不算在循环节内,直接输出
        {
            printf("%d", int(num * 10 / y));
            num = num * 10 % y;
        }
        bb = num; // 循环节开始时的余数,第二个循环节头,即循环结束位置,应与此余数相同
        if(num) // 需要判断当前余数是否为零,否则某些输出的末尾会带有(0)导致输出格式问题
        {
            printf("(");
            printf("%d", int(num * 10 / y));
            num = num * 10 % y; // 这两句不可少,若为1/3,则结果为没有前置小数的一位循环节0.(3),需特殊处理
            while(num != bb)
            {
                printf("%d", int(num * 10 / y));
                num = num * 10 % y;
            }
            printf(")");
        }
        printf("\n");
    }
    return 0;
}


原创程序,因为没有看到合适的题目能提交,不能严谨地验证程序正确性,故若有bug欢迎指正。
0 0
原创粉丝点击