C++ 为什么acos()会导致;南区(工业区)“;当使用点积的结果时?

C++ 为什么acos()会导致;南区(工业区)“;当使用点积的结果时?,c++,armadillo,math.h,C++,Armadillo,Math.h,我对这个问题很困惑。我正在运行的代码是: double dotProduct = dot(A, B); std::cout << dotProduct << std::endl; theta = acos(dotProduct); std::cout << theta << std::endl; 然而,以下工作: double dotProduct = dot(A, B); std::cout << dotProduct <&l

我对这个问题很困惑。我正在运行的代码是:

double dotProduct = dot(A, B);
std::cout << dotProduct << std::endl;
theta = acos(dotProduct);
std::cout << theta << std::endl;
然而,以下工作:

double dotProduct = dot(A, B);
std::cout << dotProduct << std::endl;
dotProduct = -1;
theta = acos(dotProduct);
此外,如果我将dotProduct强制转换为浮点,acos()会正确输出角度:

double dotProduct = dot(A, B);
std::cout << dotProduct << std::endl;
theta = acos((float) dotProduct);

对于dot()函数,我使用Armadillo库。我不明白的是,当我设置dotProduct=-1时,为什么acos()应该工作,而当它由dot()函数输出时,acos()将不工作。我做错了什么?

我假设
A
B
是标准化向量,因此您希望
点(A,B)
介于
-1
1
之间。对于浮点数学,这不一定是真的<代码>|点(A,B)可以略大于
1
。我敢打赌,如果您以更高的精度打印它,您将看到您的值略小于
-1

因此,您需要将
点(A,B)
夹在
-1
1
之间。如果输入介于
-1
1
之间,则最好只调用
acos()

double safe_acos(double value) {
    if (value<=-1.0) {
        return <pi>;
    } else if (value>=1.0) {
        return 0;
    } else {
        return acos(value);
    }
}
double-safe\u-acos(双值){
如果(值=1.0){
返回0;
}否则{
返回acos(值);
}
}
这可能会稍微快一点,因为您可以避免调用
acos()
来获取超出范围的值


注意:如果你做3D数学,你很有可能完全避免调用
acos()
。使用三角恒等式,通常我们可以用更快、更精确的解来代替它。

很可能
dot_product
返回的值略大于1,并且在输出流中插入
double
的默认格式不能完全显示值。在
double
之前插入
std::setprecision(99)
应该会显示它。将其转换为
float
将舍入到最近的可表示的
float
,因为该值非常接近于1,所以正好是1。如果@ericpostischil是正确的,则可以使用
dotProduct=std::clamp(dotProduct,-1,1.)(注意,我的“略大于一”应该是“略大于一的大小”。例如。,−1.00001…)
double dotProduct = dot(A, B);
std::cout << dotProduct << std::endl;
theta = acos((float) dotProduct);
-1
ANGLE: 3.14159
double safe_acos(double value) {
    if (value<=-1.0) {
        return <pi>;
    } else if (value>=1.0) {
        return 0;
    } else {
        return acos(value);
    }
}