USACO算法系列二——fracdec

    题目在:http://www.nocow.cn/index.php/Translate:USACO/fracdec

    题目大意是,给出两个数,求出它们的商,小数中循环部分用括号括起来。

    刚拿到这道题的时候,没有很好的想法,觉得如果直接double表示商,然后提取每位小数位判断是否循环。但是这样会出现以下问题:由于在C语言中,双精度(double)型占8 个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308,可提供16位有效数字。 也就是他的小数位最多只有16位。

    因此,只能用长除法来解决。所谓长除法其实跟我们小学学的除法相似。

    我们知道只有当出现了曾经出现过的余数时,小数部分才会出现重复。重复的部分就是自从我们上次见到同样的余数之后计算出的部分。 
    因此,我们先读入并打印整数部分。接下来,我们对剩下的真分数部分进行长除直到我们发现了重复的余数或余数变为0。如果我们发现了重复的余数,即出现了循环节,就分别恰当地打印重复的部分和不重复的部分。如果余数变为0,即已经除尽,就打印整个小数部分。如果小数位根本没有被生成,那么打印一个0就是正确答案了。代码如下:

    

    它的想法是计算循环开始前的小数位数,这样你甚至无需保存各个小数位和余数,程序的空间花费将大幅减小,而运行速度也能有所提高。我们知道2和5的幂是仅有的两种不导致循环的数,因此要找到循环前的各数位,我们只需分别找到分子分母中包含的因子2和5个数的差,再取两者的最大值(详见代码片段)。然后我们仅使用第一个余数,在计算时输出各个数位即可。

     刚开始觉得没有道理,但是通过自己亲自动手验证一下,发现确实是可以通过数学证明的。(为什么是2和5呢?因为小数可以当做一个数除以10得到的)。代码如下:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值