我正在编写一个程序,试图找到k> 1的最小值,以使a和b(均已给出)的第k个根等于整数。
这是我的代码的片段,我已对其进行注释以供澄清。
int main()
{
// Declare the variables a and b.
double a;
double b;
// Read in variables a and b.
while (cin >> a >> b) {
int k = 2;
// We require the kth root of a and b to both be whole numbers.
// "while a^{1/k} and b^{1/k} are not both whole numbers..."
while ((fmod(pow(a, 1.0/k), 1) != 1.0) || (fmod(pow(b, 1.0/k), 1) != 0)) {
k++;
}
几乎,我读了(a,b),我从k = 2开始,递增k直到a和b的第k个根都与0 mod 1一致(这意味着它们可以被1整除,因此整数)。
但是,循环无限运行。我已经尝试过研究,但我认为这可能与精度误差有关。但是,我不太确定。
我尝试过的另一种方法是更改循环条件,以检查a ^ {1 / k}的底限是否等于a ^ {1 / k}本身。但这又是无限运行的,可能是由于精度误差造成的。
有人知道我该如何解决这个问题?
编辑:例如,当(a,b)=(216,125)时,我想让k = 3,因为216 ^(1/3)和125 ^(1/3)都是整数(即, 5和6)。
答案 0 :(得分:7)
那不是编程问题,而是数学问题:
如果
a
是实数,而k
是正整数,并且如果a^(1./k)
是整数,则a
是整数。 (否则,目的是使玩具具有近似误差)
因此最快的方法可能是首先检查a
和b
是否为整数,然后执行prime decomposition使得a = p 0 e 0 * p 1 e 1 * ...,其中p 我是不同的素数。
请注意,对于a 1 / k 为整数,每个e i 也必须可被k整除。换句话说,k必须是e i 的公约数。如果b 1 / k 为整数,则b的质数必须相同。
因此,最大的k
是a
和b
的所有e i 中的greatest common divisor。
使用您的方法,您将遇到大量问题。所有IIEEE 754 binary64浮点(x86上为double的情况)都有53个有效位。这意味着所有大于2 53 的double都是整数。
函数pow(x,1./k)
将为两个不同的x
产生相同的值,因此使用您的方法时,您将必须得到错误的答案,例如数字5 5 * 2 90 和3 5 * 2 120 可以用double精确表示。该算法的结果为k=5
。您可能会发现带有这些数字的k
值,但您还会发现{<1up} 5 * 2 90 -2 49的k=5
和3 5 * 2 120 ,因为pow(5 5 * 2 90 -2 < sup> 49 ,1。/ 5)== pow(5 5 * 2 90 )。演示here
另一方面,由于只有53个有效位,因此double的质数分解是微不足道的。
答案 1 :(得分:4)
浮点数不是数学实数。计算是“近似的”。参见http://floating-point-gui.de/
您可以用StartScreenPage
之类的东西代替测试fmod(pow(a, 1.0/k), 1) != 1.0
(并使用各种类似的代替fabs(fmod(pow(a, 1.0/k), 1) - 1.0) > 0.0000001
;也请参见std::numeric_limits::epsilon,但请谨慎使用,因为{{ 1}}可能会在计算中出现一些错误,并且0.0000001
还会带来不精确的信息-细节非常复杂,请深入了解IEEE754规范)。
当然,您可以(并且应该应该)定义您的pow
函数(并使用它代替1.0/k
,并使用其否定词代替bool almost_equal(double x, double y)
)。
根据经验,切勿测试浮点数是否相等(即==
),而应考虑它们之间的足够小的距离;也就是说,将!=
(分别为==
)之类的测试替换为x == y
(分别为x != y
),其中fabs(x-y) < EPSILON
是一个小的正数,因此进行测试L1 distance较小(用于平等,而对于不平等则有足够大的距离)。
并避免在整数问题中出现浮点数。
实际上,预测或估计浮点精度非常困难。您可能需要考虑使用CADNA之类的工具。我的同事FranckVédrine是静态程序分析器的专家,可以估计数值误差(例如,参见他的TERATEC 2017 presentation on Fluctuat)。这是一个困难的研究主题,另请参见D.Monniaux的论文the pitfalls of verifying floating-point computations等。
浮点错误did in some cases导致人员伤亡(或数十亿美元的损失)。在网上搜索详细信息。在某些情况下,计算出的数字的所有数字是错误的(因为错误可能会累积,并且最终结果是通过组合数千个运算获得的)!与chaos theory之间存在间接关系,因为许多程序可能都有一些numerical instability。
答案 2 :(得分:1)
正如其他人所提到的,比较浮点值是否相等是有问题的。如果找到直接使用整数的方法,则可以避免此问题。一种方法是将整数提高到k
的幂,而不是取第k
的根。这些细节留给读者练习。