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

math.h pow() function not working correctly?

本文关键字:常工作 工作 函数 pow Math 不能      更新时间:2023-10-16

我正在做一个个人项目,我需要确定0到999之间的所有质数幂。因为我不是特别擅长数学,所以我尝试了以下笨拙的暴力方法。

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);
}

现在,如果我调用我的_pow()版本,而不是从math.h调用pow(),则输出显示为例外。我的实现错了吗?如果不是,则来自math.h的pow()无法正常工作。知道是什么原因造成的吗?

问题是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,可以将其更改为任何你想要的整型)

您永远不需要验证一个数是否能整除它自己,以及一个数是否能整除一个数。这是无用的:imp % imp == 0 && imp % 1 == 0

否则,问题在于pow在与整数比较时返回双精度或浮点数。由于舍入误差,比较可能失败。我建议您实现自己的整数幂运算,以避免任何舍入错误。或者将i转换为double,并使用具有较小epsylon公差的比较。