Вполне ожидаемо, что вы не сможете получить точные нулевые выходы для косинуса всего с плавающей запятой, независимо от того, насколько хорош ваш подход к вычислениям. Это фундаментально для того, как работает плавающая точка.
Математические нули косинуса - это нечетные кратные числа пи / 2. Поскольку pi иррационально, оно не совсем представимо в виде двойного числа (или любой формы с плавающей запятой), и разница между ближайшими соседними значениями, которые представимы, будет, по крайней мере, в пи / 2 раза DBL_EPSILON
, примерно 3e-16
(или соответствующие значения для других типов с плавающей запятой). Для некоторых нечетных кратных числа pi / 2 вам может «повезти» и вы обнаружите, что он действительно близок к одному из двух соседей, но в среднем вы обнаружите, что он находится на расстоянии 1e-16
. Таким образом, ваш ввод уже неверен на 1e-16
или около того .
Теперь косинус имеет наклон +1 или -1 в своих нулях, поэтому ошибка на выходе будет примерно пропорциональнаошибка на входе. Но чтобы получить точный ноль, вам понадобится ошибка меньше, чем наименьший представимый ненулевой дубль, который составляет около 2e-308
. Это почти на 300 порядков меньше, чем погрешность на входе.
В то время как вы теоретически можете «повезти» и получите несколько кратных, если pi / 2 действительно очень близко к ближайшему представимому двойному значению, вероятностьэто, просто моделирование его как случайного, астрономически мало. Я полагаю, что есть даже доказательства того, что нет двойного x
, для которого правильно округленное значение cos(x)
является точным нулем. Для одинарной точности (float
) это можно легко определить методом грубой силы;для double
это, вероятно, также выполнимо, но большое вычисление.
Что касается того, почему printf
печатает -0.000000
, просто для %f
по умолчанию используется 6 знаков после десятичной точки, чтонедостаточно близко, чтобы увидеть первую значащую цифру. Использование %e
или %g
, опционально с модификатором большой точности, покажет вам приблизительный результат, который вы получили, который действительно сохраняет некоторую значимость, и даст вам представление о том, хорош ли ваш результат.