毕达哥拉斯恒等式:如何计算正确的 cos 符号?
Pythagorean identities: how do I calculate the proper cos sign?
有公式
cos(x) = sqrt(1-sin(x)^2)
我正在尝试在我的简单程序中对其进行测试,但我不明白我的错在哪里。
最后结果不对
#include <iostream>
#include <vector>
#include <cmath>
int main() {
std::vector<float> data;
constexpr float angleAdd = 360.0/10.0;
constexpr float M_PI_DIVIDED_BY_180 = M_PI/180.0;
for (auto angle = 0.0; angle < 360.0; angle += angleAdd) {
data.push_back(angle);
}
//
float res1 = 0;
for (int i = 0; i < data.size(); ++i) {
res1 += sin(data[i]*M_PI_DIVIDED_BY_180);
res1 += cos(data[i]*M_PI_DIVIDED_BY_180);
}
std::cout << "\n\n";
float res2 = 0;
for (int i = 0; i < data.size(); ++i) {
float angle = data[i];
float sinVal = sin(angle*M_PI_DIVIDED_BY_180);
bool isPositiveSign = (angle >= 0 && angle <= 90) || (angle >= 270 && angle <= 360);
float cosVal = sqrt(1 -sinVal*sinVal);
if (isPositiveSign) {
cosVal = fabs(cosVal);
} else {
cosVal = -1.0*fabs(cosVal);
}
res2 += sinVal;
res2 += cosVal;
}
std::cout << "res1: " << res1 << " res2: " << res2 << std::endl;
return 0;
}
它给了我:
res1: -6.89606e-07 res2: -3.57628e-07
显然,res2
是错误的。
我确定我对 cos 符号的计算有问题,但我无法弄清楚 - 是什么。
社区可以给我一些提示这里有什么问题吗?
如果您可以无误地进行计算,则您计算为 res1
或 res2
的数字将为零。但是,浮点运算总是会出错。因此,您获得的两个不同结果只是浮点零对计算精度的两种不同表示形式——以双精度进行计算,您会发现幅度较小的结果。
另请注意,std::cos()
和 std::sin()
并不 完全 满足恒等式 square(sin)+square(cos)=1
。因此,
assert(square(std::cos(x)) != 1 - square(std::sin(x)));
对于 x
的大多数值(例外情况大概只有 0 或 pi)。
由于 res1
和 res2
都是零的近似值,它们的符号是任意的(尽管是确定性的)。如果将 angleAdd
更改为 360
.
的另一个除数,您将得到不同的结果(但仍然与零的近似值一致)
当然,所有这些都意味着您的程序不测试 res1
和 res2
的任何值,这些值在零 std::numeric_limits<X>::epsilon()
范围内(其中 X
是使用的浮点类型)是有效的。没有正确答案。
有公式
cos(x) = sqrt(1-sin(x)^2)
我正在尝试在我的简单程序中对其进行测试,但我不明白我的错在哪里。 最后结果不对
#include <iostream>
#include <vector>
#include <cmath>
int main() {
std::vector<float> data;
constexpr float angleAdd = 360.0/10.0;
constexpr float M_PI_DIVIDED_BY_180 = M_PI/180.0;
for (auto angle = 0.0; angle < 360.0; angle += angleAdd) {
data.push_back(angle);
}
//
float res1 = 0;
for (int i = 0; i < data.size(); ++i) {
res1 += sin(data[i]*M_PI_DIVIDED_BY_180);
res1 += cos(data[i]*M_PI_DIVIDED_BY_180);
}
std::cout << "\n\n";
float res2 = 0;
for (int i = 0; i < data.size(); ++i) {
float angle = data[i];
float sinVal = sin(angle*M_PI_DIVIDED_BY_180);
bool isPositiveSign = (angle >= 0 && angle <= 90) || (angle >= 270 && angle <= 360);
float cosVal = sqrt(1 -sinVal*sinVal);
if (isPositiveSign) {
cosVal = fabs(cosVal);
} else {
cosVal = -1.0*fabs(cosVal);
}
res2 += sinVal;
res2 += cosVal;
}
std::cout << "res1: " << res1 << " res2: " << res2 << std::endl;
return 0;
}
它给了我:
res1: -6.89606e-07 res2: -3.57628e-07
显然,res2
是错误的。
我确定我对 cos 符号的计算有问题,但我无法弄清楚 - 是什么。
社区可以给我一些提示这里有什么问题吗?
如果您可以无误地进行计算,则您计算为 res1
或 res2
的数字将为零。但是,浮点运算总是会出错。因此,您获得的两个不同结果只是浮点零对计算精度的两种不同表示形式——以双精度进行计算,您会发现幅度较小的结果。
另请注意,std::cos()
和 std::sin()
并不 完全 满足恒等式 square(sin)+square(cos)=1
。因此,
assert(square(std::cos(x)) != 1 - square(std::sin(x)));
对于 x
的大多数值(例外情况大概只有 0 或 pi)。
由于 res1
和 res2
都是零的近似值,它们的符号是任意的(尽管是确定性的)。如果将 angleAdd
更改为 360
.
当然,所有这些都意味着您的程序不测试 res1
和 res2
的任何值,这些值在零 std::numeric_limits<X>::epsilon()
范围内(其中 X
是使用的浮点类型)是有效的。没有正确答案。