Пифагорейские тождества: как рассчитать правильный знак cos?

Имея формулу

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, но я не могу понять — что.
Может ли сообщество дать мне несколько советов, что здесь не так?

0

Решение

Число, которое вы вычисляете как 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 используется тип с плавающей точкой). Здесь нет правильный ответ.

1

Другие решения


По вопросам рекламы [email protected]