Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Математические расчеты в Java


Автор: Гость_Владимир 1.11.2005, 11:57
День добрый!

Есть задачка, где нужен cos(Pi/2). Насколько я знаю из школьного курса математики, это равно 0.

Однако, получается следующая ерунда:

fi = (Math.Pi/2);
cos_fi = Math.cos(fi);

А в результате Cos угла fi оказывается равен 6.....Е-17.

Почему так?

Заранее благодарен.
С уважением.

Автор: LSD 1.11.2005, 12:01
Погрешность вычислений. ИМХО 17-й знак после запятой вполне приемлимая точность.

Автор: Гость_Владимир 1.11.2005, 14:21
А если данное значение подставляется в формулу, то можно ли его считать нулем?

Заранее спасибо.

Автор: LSD 1.11.2005, 14:34
Если умножать некое большое число на 0.00000000000000006, то конечно ноль мы не получим. Но промежуточные результаты можно округлять например.

Автор: Гость_Владимир 1.11.2005, 15:33
Благодарствую!

Автор: NotGonnaGetUs 1.11.2005, 15:40
Цитата
fi = (Math.Pi/2);
cos_fi = Math.cos(fi);

А в результате Cos угла fi оказывается равен 6.....Е-17.


Потому что число PI имеет бесконечное количество знаков после запятой smile
А ты мало того, что берёшь константу ограниченную 16 знаками, так ещё делишь её на два. А как известно:

cos(pi/2 + x) = - sin(x) = -x (при х->0)

вот ты и получаешь в результате число порядка 10^-16/17


Автор: val 1.11.2005, 15:59
Скорее всего вычисление происходит через нахождение суммы ряда, аппроксимирующего функцию косинуса, естественно, число членов этого ряда конечно и, как следствие, наличие погрешности аппроксимации, которая и отражается в семнадцатом знаке после запятой.

Автор: NotGonnaGetUs 1.11.2005, 16:40
Цитата(val @ 1.11.2005, 15:59)
число членов этого ряда конечно

точность членов ряда тоже конечна.


как бы то ни было, что заказали, то и получили - величину отклонение fi от истинного значения pi/2 smile


вот пример:
[quot]
double fi = (Math.PI/2)+0.000001;
double cos_fi = Math.cos(fi);
System.out.println("cos: " + cos_fi);
[/quot]

Получаем "cos: -9.999999998563343E-7" - т.е. то самое отклонение.

Автор: Guest 4.11.2005, 12:03
Цитата(NotGonnaGetUs @ 1.11.2005, 15:40)
Цитата
fi = (Math.Pi/2);
cos_fi = Math.cos(fi);

А в результате Cos угла fi оказывается равен 6.....Е-17.


Потому что число PI имеет бесконечное количество знаков после запятой smile
А ты мало того, что берёшь константу ограниченную 16 знаками, так ещё делишь её на два. А как известно:

cos(pi/2 + x) = - sin(x) = -x (при х->0)

вот ты и получаешь в результате число порядка 10^-16/17



Хм. Почему же тогда:

fi = (Math.Pi/2);
sin_fi = Math.sin(fi);

В результате синус фи = 1. Т.е. с косинусом такие вещи не прокатывают, а с синусом со свистом?

Автор: maxim1000 4.11.2005, 13:55
есть абсолютная погрешность, а есть относительная
при сохранении в double сохраняется мантисса и порядок числа
так что в случае с 0.00000001 сохраняется 1e-8 (если не обсчитался нулей)
а если 1.00000001, то придется сохранить 1.00000001e0
так вот точность самой мантиссы ограничена, 1 запомнить просто, а 1.00000001 - нужно достаточно бит...
Добавлено @ 13:56
т.е. в случае синуса тоже получилось 1.00...001 (например), но из-за погрешности это просто обрезалось...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)