2014-11-21 5 views
-1

M_PI - это макрос, который определен как 3.14159265358979323846, который кажется более точным, чем двойной. Я пытаюсь получить ответ в поплавке, и никакое количество кастингов мне не поможет, результат всегда будет 6.12323426e-017 или -4.37113883e-008, если я попробую слить M_PI в поплавок.Как обрабатывать результат cos (M_PI/2)

Ответ должен быть 0, и я хотел бы сохранить это в поплавке.

+0

Это кажется точным, как двойной. – Teepeemm

+0

Единственное рациональное число 'x', для которого' cos (x) 'рационально -' 0'. Все числа с плавающей запятой являются рациональными; Действительно, они являются рациональными, знаменатель которых является степенью двух. Ваши ожидания ошибочны, а не косинус вашей библиотеки. – tmyklebu

ответ

3

это невозможно. Невозможно представить точное значение pi в конечном типе данных с плавающей запятой.

В общем, вы не можете ожидать, что любая операция над значениями с плавающей запятой будет в точности равна соответствующей математической операции над реальными значениями. Обычный подход заключается в сравнении с допуском, в этом случае, возможно, что-то вроде

if (std::abs(result) < tolerance) { 
    // treat it as zero 
} 

Выбор подходящего значения tolerance, чтобы получить точность, что нужно для вашей конкретной проблемы является сложная часть.

+2

Просто для добавления - есть 'FLT_EPSILON' и' DBL_EPSILON' в ''. – Paul

+3

@Paul: В некоторых случаях они могут быть разумным руководством к разумной толерантности (если вы ожидаете ответа около 1). Но в целом вам нужно проанализировать вашу проблему и вероятный диапазон значений, с которыми вы имеете дело, найти подходящий перенос, который может сильно отличаться от этих значений. –

+0

@Paul: Вы знаете, что это такое, не так ли? И вы знаете, почему они не просто допуски, что вы используете волей-неволей, не так ли? – tmyklebu

-1

Поскольку представление pi с плавающей точкой никогда не будет ближе к pi, чем машинный epsilon, косинус этого значения над двумя будет аналогично отличаться от ожидаемого результата 0. Математически значение с плавающей запятой pi может быть представлена ​​в виде пи + EPS, и, таким образом, значение вызова функции будет

cos(pi/2 + eps/2) = -sin(eps/2) ~= -eps/2. 
+0

Не понимайте голосующий голос - просто попробуйте объяснить OP, что ожидается, что результат cos (M_PI/2) будет небольшим числом. – sfjac

1

тем фактом, что M_PI макро использует большую точность, чем двойник, не меняет тот факт, что аргумент функции сов, M_PI/2 рассчитывается как двойной.

Итак, вместо вычисления косинуса точного числа «pi/2», равного 0, вы вычисляете косинус числа с плавающей запятой, ближайшего к «pi/2». Следовательно, результат будет неточно 0.

Никакое количество кастинга не изменится.

Смежные вопросы