这是一个家庭作业问题。给定具有两个整数字段(分子和分母)的类“Rational”,编写一个函数来比较两个“Rational”实例。设r1 = a/b
和r2 = c/d
。简单的解决方案是比较a*d
和b*c
。我们可以做得更好吗?
答案 0 :(得分:4)
在一般情况下,没有。如果你希望进行大量的比较,初步处理步骤可以处理所有事情的规范化(通过将分子和分母除以它们的gcd,并使分母为正),以便相等比较将比较a = c和b = d,但计算a * d = b * c肯定不会以任何方式禁止。
答案 1 :(得分:4)
如果您需要复杂的解决方案,请将两个分数中的每一个转换为连续分数(使用GCD算法的变体)。这个简单的算法一次生成一个整数。比较两个部分连续分数中的每对整数。如果它们不同,请退出。否则生成下一对并继续,而有更多。 对于有理数,序列是有限的,因此很快就会终止。 我相信这是a,b,c,d很大的最佳方法。
已经证明,所有平方根非理性的连续分数扩张是重复出现的。所以你也可以使用它来比较那些非理性,即使它们的二进制计算机表示会给你一个错误的结果(由于截断)。 这意味着只要您检测到模式中的重复,就可以终止,证明两个非理性的相等。
答案 2 :(得分:3)
通常分支的成本高于乘法的成本,因此除了那个之外,不值得尝试。如果用整数表示int32,则提升为int64以执行乘法运算;如果你的意思是更大的整数,那么你需要使用通常的机制来管理乘法,此时关于分支的假设可能会失效。
答案 3 :(得分:2)
从我的观点来看,如果允许负数,那么简单的解决方案是不正确的:
r1=1/3
和b=1/(-3)
怎么样都应该是正确的有理数。当然,从数学角度来看,它认为:
1 /( - 3)< 1/3
但是,建议的解决方案会产生1*3 > 1*(-3)
,导致1/3 < 1/(-3)
的错误解决方案。
我刚刚在Scala课程中遇到了这个问题:-)但我仍然没有很好的解决方案。
也许,像往常一样有助于调查BOOST-Library:它说:
比较合理操作执行两个双倍大小的GCD操作,两个额外的添加和减少,以及最坏情况下的三个比较。 (GCD操作是双倍大小的,因为它们是零碎的,临时商保留并进行比较,而直接GCD功能只保留并比较余数。)
http://www.boost.org/doc/libs/1_55_0/libs/rational/rational.html
到目前为止,我还没有机会调查该代码。
干杯, 菲利克斯
与此同时,我看了一下Boost代码,就像Liberius在上面的回答中描述的那样。 https://stackoverflow.com/a/4288890/2682209 所以这绝对是&#34;正确&#34; (但很麻烦)的方式。
答案 4 :(得分:1)
我不喜欢a*d b*c
解决方案,因为如果某些分子和分母很大,它可能会导致不必要的整数溢出。虽然我没有更好的解决方案。
答案 5 :(得分:0)
如果你正在使用Java,那么你可以在遇到溢出时使用java.math.BigInteger
类;否则,您可以实现自己的via byte-arrays。