C++ 在C+中查找立方根+;?

C++ 在C+中查找立方根+;?,c++,math.h,pow,C++,Math.h,Pow,当我试图找到一个数字的立方根时,会发生奇怪的事情 下面的代码返回未定义的值。在cmd中:-1.#IND coutpow(x,y)如果x为负,y为非整数,则来自的pow(x,y)不起作用 这是std::pow的一个限制,如C标准和上所述: 错误处理 按照math_errhandling中的规定报告错误 如果基为有限且为负,exp为有限且为非整数,则会发生域错误和范围错误。 如果base为零,exp为零,则可能发生域错误 如果基为零,exp为负,则可能发生域错误或极错误 有两种方法可以解决此限制

当我试图找到一个数字的立方根时,会发生奇怪的事情

下面的代码返回未定义的值。在cmd中:-1.#IND

cout
pow(x,y)
如果x为负,y为非整数,则来自
的pow(x,y)不起作用

这是
std::pow
的一个限制,如C标准和上所述:

错误处理

  • 按照math_errhandling中的规定报告错误
  • 如果基为有限且为负,exp为有限且为非整数,则会发生域错误和范围错误。
  • 如果base为零,exp为零,则可能发生域错误
  • 如果基为零,exp为负,则可能发生域错误或极错误
有两种方法可以解决此限制:

  • 多维数据集根与将某个东西取1/3幂相同,因此可以执行
    std::pow(x,1/3.)

  • 在C++11中,可以使用。C++11引入了平方根和立方根函数,但没有通用的n次根函数可以克服
    std::pow
    的限制


不要使用
(double)
强制转换为
双精度
,而是使用双精度数值常量:

double thingToCubeRoot = -20.*3.2+30;
cout<< thingToCubeRoot/fabs(thingToCubeRoot) * pow( fabs(thingToCubeRoot), 1./3. );
double thingToCubeRoot=-20.*3.2+30;

我猜你得把底片拿出来然后放进去。如果你真的愿意,你可以让一个包装器帮你做这件事

function yourPow(double x, double y)
{
    if (x < 0)
        return -1.0 * pow(-1.0*x, y);
    else
        return pow(x, y);
}
函数yourPow(双x,双y)
{
if(x<0)
返回-1.0*pow(-1.0*x,y);
其他的
返回功率(x,y);
}
当(-1)^3=-1时,你不能简单地接受负数的有理幂而期望得到真实的响应。这是因为对于这个有理指数还有其他的解决方案,它们本质上是虚构的。

类似地,图x^x。对于x=-1/3,应该有一个解决方案。但是,对于x<0,该函数在R中被视为未定义


因此,不要指望math.h会变魔术,那样会使它效率低下,只要自己改变符号就行了。

1/3
是一个特例。一般来说,负数的非整数幂是复杂的。对于pow来说,检查诸如整数根之类的特殊情况是不切实际的,而且,
1/3
作为双精度不是1/3

我不知道VisualC++的POW,但是我的Mman页面在错误下说:

EDOM
参数
x
为负值,
y
不是整数值。这将导致一个复数

如果你想要负数的立方根,你必须使用一个更专门的立方根函数——或者抄近路,取绝对值,然后取立方根,然后再乘以符号


请注意,根据上下文的不同,
1/3
幂的负数
x
不一定是您期望的负立方根。它可以很容易地成为第一个复数根,
x^(1/3)*e^(pi*i/3)
。这是mathematica使用的惯例;仅仅说它是未定义的也是合理的。

我认为你不应该混淆指数运算和数字的n次根。请参阅良好的旧版本

pow(x,y)
与(即等同于)exp(y*log(x))

如果日志(x)无效,则pow(x,y)也无效


类似地,你不能执行任何事情的幂次0,尽管从数学上讲它应该是0。

我在寻找cubit root并找到了这个线程,我想到以下代码可能会工作:

#include <cmath>
using namespace std;

function double nth-root(double x, double n){
    if (!(n%2) || x<0){
        throw FAILEXCEPTION(); // even root from negative is fail
    }

    bool sign = (x >= 0);

    x = exp(log(abs(x))/n);

    return sign ? x : -x;
}
#包括
使用名称空间std;
函数双n根(双x,双n){
如果(!(n%2)| | x=0);
x=exp(log(abs(x))/n);
返回标志?x:-x;
}

因为1/3将始终返回0,因为它将被视为整数。。。 尝试使用1.0/3.0。。。 这是我的想法,但尝试并实施。。。
不要忘记将包含1.0和3.0的变量声明为double…

C++11具有
cbrt
函数(参见示例),因此您可以编写如下代码

#include <iostream>
#include <cmath>

int main(int argc, char* argv[])
{
   const double arg = 20.0*(-3.2) + 30.0;
   std::cout << cbrt(arg) << "\n";
   std::cout << cbrt(-arg) << "\n";
   return 0;
}
#包括
#包括
int main(int argc,char*argv[])
{
常数双参数=20.0*(-3.2)+30.0;

std::cout这是我设计的一个小函数

#define uniform() (rand()/(1.0 + RAND_MAX))

double CBRT(double Z)
{
    double guess = Z;
    double x, dx;
    int loopbreaker;

retry:
    x = guess * guess * guess;
    loopbreaker = 0;
    while (fabs(x - Z) > FLT_EPSILON)
    {
        dx = 3 * guess*guess;
        loopbreaker++;
        if (fabs(dx) < DBL_EPSILON || loopbreaker > 53)
        {
            guess += uniform() * 2 - 1.0;
            goto retry;
        }
        guess -= (x - Z) / dx;
        x = guess*guess*guess;
    }

    return guess;
}
#定义统一()
双CBRT(双Z)
{
双猜测=Z;
双x,dx;
内环断路器;
重试:
x=猜测*猜测*猜测;
环路断路器=0;
while(fabs(x-Z)>FLT_ε)
{
dx=3*猜测*猜测;
环路断路器++;
if(fabs(dx)53)
{
guess+=uniform()*2-1.0;
转到重试;
}
猜测-=(x-Z)/dx;
x=猜测*猜测*猜测;
}
返回猜测;
}
它使用Newton Raphson来找到一个立方根

有时牛顿-拉斐逊被卡住了,如果根非常接近于0,那么导数可以 当它变大时,它可能会振荡。所以我钳制了它,并强迫它重新启动。
如果您需要更高的精度,您可以更改FLT_ε。

如果您没有数学库,您可以使用此方法计算立方根:

立方根 它源于下面的
sqrt
算法。其思想是
b
x/b/b
x
的立方根开始越来越大,越来越小。因此,两者的平均值更接近
x
的立方根

平方根和立方根(Python中) 与平方根不同,立方根中需要
last_b_1
last_b_2
,因为b闪烁。您可以修改这些算法以计算第四根、第五根等

感谢我11年级的数学老师Herr Brenner,他告诉我了
sqrt
的算法

演出 我在Arduino上测试了它,时钟频率为16mhz:

  • 0.3525ms
  • 0.3853ms
  • 2.3426ms
呃,双重铸造很好,t
#include <iostream>
#include <cmath>

int main(int argc, char* argv[])
{
   const double arg = 20.0*(-3.2) + 30.0;
   std::cout << cbrt(arg) << "\n";
   std::cout << cbrt(-arg) << "\n";
   return 0;
}
#define uniform() (rand()/(1.0 + RAND_MAX))

double CBRT(double Z)
{
    double guess = Z;
    double x, dx;
    int loopbreaker;

retry:
    x = guess * guess * guess;
    loopbreaker = 0;
    while (fabs(x - Z) > FLT_EPSILON)
    {
        dx = 3 * guess*guess;
        loopbreaker++;
        if (fabs(dx) < DBL_EPSILON || loopbreaker > 53)
        {
            guess += uniform() * 2 - 1.0;
            goto retry;
        }
        guess -= (x - Z) / dx;
        x = guess*guess*guess;
    }

    return guess;
}
double curt(double x) {
  if (x == 0) {
    // would otherwise return something like 4.257959840008151e-109
    return 0;
  }
  double b = 1; // use any value except 0
  double last_b_1 = 0;
  double last_b_2 = 0;
  while (last_b_1 != b && last_b_2 != b) {
    last_b_1 = b;
    // use (2 * b + x / b / b) / 3 for small numbers, as suggested by  willywonka_dailyblah
    b = (b + x / b / b) / 2;
    last_b_2 = b;
    // use (2 * b + x / b / b) / 3 for small numbers, as suggested by  willywonka_dailyblah
    b = (b + x / b / b) / 2;
  }
  return b;
}
def sqrt_2(a):
    if a == 0:
        return 0
    b = 1
    last_b = 0
    while last_b != b:
        last_b = b
        b = (b + a / b) / 2
    return b

def curt_2(a):
    if a == 0:
        return 0
    b = a
    last_b_1 = 0;
    last_b_2 = 0;
    while (last_b_1 != b and last_b_2 != b):
        last_b_1 = b;
        b = (b + a / b / b) / 2;
        last_b_2 = b;
        b = (b + a / b / b) / 2;
    return b