给定(a,b)计算k的最大值,使得a ^ {1 / k}和b ^ {1 / k}是整数

时间:2019-01-02 15:16:46

标签: c++ algorithm c++11 math

我正在编写一个程序,试图找到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)。

3 个答案:

答案 0 :(得分:7)

那不是编程问题,而是数学问题:

  

如果a是实数,而k是正整数,并且如果a^(1./k)是整数,则a是整数。 (否则,目的是使玩具具有近似误差)

因此最快的方法可能是首先检查ab是否为整数,然后执行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的质数必须相同。

因此,最大的kab的所有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的根。这些细节留给读者练习。