Имея формулу
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 и, возможно, пи).
поскольку res1
а также res2
оба приближения нуля, их знаки произвольны (хотя и детерминированы). Если вы измените результаты, вы получите другие результаты (но все равно согласуетесь с нулевым приближением) angleAdd
другому делителю 360
,
Все это, конечно, подразумевает, что ваша программа ничего не проверяет и любые значения для res1
а также res2
которые в течение нескольких std::numeric_limits<X>::epsilon()
с нуля (где X
используется тип с плавающей точкой). Здесь нет правильный ответ.