Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ math.h pow()函数工作不正常?_C++_Primes_Math.h_Prime Factoring - Fatal编程技术网

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

C++ math.h pow()函数工作不正常?,c++,primes,math.h,prime-factoring,C++,Primes,Math.h,Prime Factoring,我在做一个个人项目,在这个项目中,我需要确定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 f

我在做一个个人项目,在这个项目中,我需要确定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;
}
然而,我得到的却是:

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,那么输出显示为excepted。我的实现错了吗?如果不是,那么math.h的pow就不能正常工作。 你知道是什么原因造成的吗?

问题是,通常双精度和浮点数都不精确,标准库中的数学函数也使用近似公式进行计算。如果调用pow2,10,可能会得到1023.999375,例如,根据上下文,它可能会被截断为1023

因此,不必使用标准库中的浮点pow函数,您可以使用自己的整数精确实现:

int constexpr _pow(int base, int exp)
{
    return exp == 0 ? 1 : base * _pow(base, exp - 1);
}
如果需要unsigned或long-long,也可以将其更改为所需的任何整数类型。

问题在于,通常情况下,双精度和浮点数并不精确,标准库中的数学函数也使用近似公式进行计算。如果调用pow2,10,可能会得到1023.999375,例如,根据上下文,它可能会被截断为1023

因此,不必使用标准库中的浮点pow函数,您可以使用自己的整数精确实现:

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

如果您需要unsigned或long-long,也可以将其更改为您想要的任何整数类型。

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


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

您无需验证一个数字是否自己除法,以及一个数字是否除法。这是无用的:imp%imp==0&&imp%1==0


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

永远不要将double与int进行比较。@Hans Passant这是我第一次听到这样的事情。有什么问题吗?编译器不应该警告我这类事情吗?@cyberpunk_u2;@HansPassant,永远不要说永远。如果double是从int赋值的,那也没关系。但在这种情况下,它不是。千万不要将double与int进行比较。@Hans Passant这是我第一次听到这样的事情。有什么问题吗?编译器不应该警告我这类事情吗?@cyberpunk_u2;@HansPassant,永远不要说永远。如果double是从int赋值的,那也没关系。不过,在这种情况下,它没有意义。到目前为止。但是为什么我仍然返回double的实现看起来有效呢?@cyberpunk\ux,您的版本有效,因为您处理的所有double都是从整数转换而来的。pow math library函数使用更快的数学运算,但它需要实际的浮点运算,这会损失一点点精度。实现powx,y的一种方法是expy*lnx,ln和exp都可能导致舍入错误。我确信真正的战俘没有使用这种方法。是否缺少下划线?@AlexeyFrunze确实有。到目前为止是有道理的。但是为什么我仍然返回double的实现看起来有效呢?@cyberpunk\ux,您的版本有效,因为您处理的所有double都是从整数转换而来的。pow math library函数使用更快的数学运算,但它需要实际的浮点运算,这会损失一点点精度。实现powx,y的一种方法是expy*lnx,ln和exp都可能导致舍入错误。我相信真正的战俘不会使用这种方法。是否缺少下划线?@AlexeyFrunze确实有。