C++ 在C+中查找立方根+;?
当我试图找到一个数字的立方根时,会发生奇怪的事情 下面的代码返回未定义的值。在cmd中:-1.#INDC++ 在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为负,则可能发生域错误或极错误 有两种方法可以解决此限制
coutpow(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