math.h pow()函数不能正常工作?

时间:2013-03-11 20:57:41

标签: c++ primes math.h prime-factoring

我正在制作一个个人项目,我需要确定0到999之间的所有prime powers。因为我不是特别擅长数学,所以我厌倦了以下火腿蛮力的暴力方法。

bool constexpr is_prime(int imp)
{
    return imp == 1 ? false : (imp % imp == 0 && imp % 1 == 0 && [&imp]{ for(int i = 2; i < imp; ++i)  if(imp % i == 0) return false; return true;}());
}

bool is_prime_power(int imp)
{
    for(int i = 1; i < 1000; ++i)
        if (is_prime(i))
            for (int j = 0; j < 100; ++j)
                if (imp == pow(i, j))
                    return true;
    return false;
}

对于0 ... 30,输出应该是(根据A000961):

1 2 3 4 5 7 8 9 11 13 16 17 19

然而,这就是我所得到的:

1 2 3 4 5 7 8 9 11 16 19

13和17哪里消失了?

由于我的方法无法找到任何逻辑问题,因此我实现了自己的pow()函数。

double constexpr _pow(double base, double exp)
{
    return exp == 0 ? 1 : base*pow(base, exp - 1);
}

现在,如果我从math.h调用我的_pow()而不是pow(),则输出显示为例外。我的实施错了吗?如果没有,math.h中的pow()无法正常工作。 知道是什么导致了这个吗?

2 个答案:

答案 0 :(得分:3)

问题是double(和一般的浮点数)不准确,标准库中的数学函数也使用近似公式进行计算。如果您致电pow(2, 10),您可能会获得1023.999375(根据具体情况,可能会被截断为1023)。

因此,不是使用标准库中的浮点pow()函数,而是可以使用自己的完全实现整数:

int constexpr _pow(int base, int exp)
{
    return exp == 0 ? 1 : base * _pow(base, exp - 1);
}

(或者如果您需要unsignedlong long,请将其更改为您想要的任何整数类型。

答案 1 :(得分:1)

您永远不需要验证一个数字是否分开,而一个数字除以一个数字。这没用:imp % imp == 0 && imp % 1 == 0

否则你遇到的问题是因为pow会在将它与整数进行比较时返回double或float。由于舍入误差,comaparison可能会失败。我建议你实现自己的整数幂操作,以避免任何舍入错误。或者将i转换为double并使用与一些小epsylon容差的比较。