【发布时间】:2018-07-13 19:00:40
【问题描述】:
给你一个整数n和一个有理数p/q(p和q是整数) .
你如何比较 sqrt(n) 和 p/q?
解决方案 1:sqrt(n) <= (double) p / q
应该可以,但调用sqrt 比仅使用乘法/除法要慢。
解决方案 2: (double) n * q * q <= p * p
更好,但我不禁想到,因为我们使用的是浮点数,如果 p/q 非常接近 sqrt(n),我们可能会得到一个不正确的答案。此外,它需要将整数转换为浮点数,这(略微)比仅使用整数要慢。
解决方案 3:n*q*q <= p*p
更好,但是如果 p 和 q 由于溢出而变大(通常是 p 或 q em> >= 2^32 当使用 64 位整数时)。
解决方案 4:将解决方案 3 与 bignum 库/在具有未绑定整数的编程语言中结合使用。
解决方案 5: (q / p) * n <= p / q
成功避免了任何溢出问题,但我不确定这在所有情况下都是正确的,因为整数除法......
所以...我很乐意使用解决方案 2 或 4,但我想知道是否有人有聪明的技巧来解决这个问题,或者可能是解决方案 5 有效(或无效)的证明(或反例)。
【问题讨论】:
-
浮点不一定比整数慢。见stackoverflow.com/questions/2550281/…
-
5 的反例:
n = 4; p = 2; q = 1;预期结果:sqrt(n) == p/q;实际结果:(1 / 2) * 4整数除法为4,而2/1为2,产生4 <= 2这是错误的。 -
您认为一种解决方案比另一种解决方案更好的标准是什么?或者标准是什么?正如您的问题所暗示的那样,您是否只关心可以 32 位或 64 位表示的整数?
-
@HighPerformanceMark 标准将是效率和优雅。关于整数:问题只出现在我的设置中的 64 位。如果我有 32 位或更少的整数,我可以使用 64 位来进行计算并且我没有溢出问题。如果我有超过 64 位的整数,那么溢出也不会成为问题(因为我将使用 bignum 库)。但问题仍然可以转化为任何大小:当您的输入有 n 位,但您的计算不能使用超过 2*n-1 位时。跨度>
-
在不知道 n,p,q 上界的情况下,答案是 4,使用 bignum
标签: performance math floating-point