Столкнулся с проблемой в Math
:
double a = 0.0;
double b = Math.toRadians(a);
System.out.println(Math.cos(b));
Вывод: 1.0
.
double a = 90.0;
double b = Math.toRadians(a);
System.out.println(Math.cos(b));
Вывод: 6.123233995736766E-17
.
Почему Java подсчитывает 90 градусов неверно?
Обратите внимание, программа вывела не просто 6.123233995736766
, а 6.123233995736766E-17.
Это представление (с «E») называется научной нотацией. В ней числа имеют вид:
±mmmmE±pppp
где:
Таким образом, 6.123233995736766E-17 превращается в 0.00000000000000006123233995736766.
Так а все верно.
6.123233995736766E-17
это почти 0, такой ответ связан с точностью представления чисел с плавающей точкой.
PS: Сравнивать double в этом случае нужно примерно так, если Вас устраивает такая точность...
boolean isEqual(double d1, double d2){
return Math.abs(d1 - d2) < 1e-10;
}
Метод cos()
вычисляет косинус, используя бесконечную сумму (у меня нет инсайдерских данных, просто по-другому это реализовать проблематично: *P.S.). Чем больше слагаемых, тем точнее вычисления.
Примерно так он реализован:
double cos(double x, int precision) {
double result = 0;
for (int i = 0; i < precision; i++) {
result += Math.pow(x,2*i)/factorial(2*i);
i++;
result -= Math.pow(x,2*i)/factorial(2*i);
}
return result;
}
ArrayList<Double> factorialCache = new ArrayList<>();
{
factorialCache.add(1D);
}
double factorial(int n) {
if (n < factorialCache.size()) return factorialCache.get(n);
double result = factorialCache.get(factorialCache.size() - 1);
for (int i = factorialCache.size(); i <= n; i++)
factorialCache.add(result *= i);
return result;
}
На достаточно небольших числах, порядка десяти, факториал начинает немыслимо быстро расти. Чтобы производить точные вычисления на очень больших и очень маленьких числах, необходимо вместо double
использовать BigDecimal
, но с ним вычисления происходят намного дольше, чем с double
, поэтому разработчиками явы принято решение пожертвовать точностью взамен производительности. При желании вы можете сами написать более точный метод для определения косинуса.
При точности (precision
) 12
(или 11
) метод возвращает 4.245771032544636E-17
, немного меньше, чем стандартный метод. Меньше при использовании double
получить не получится.
P.S.: В принципе можно реализовать вычисление косинуса ещё и с помощью формулы Эйлера о синусе и косинусе, но там нужно реализовывать класс, представляющий комплексные числа. Ещё можно сохранить "транспортир" в виде массива косинусов при разных углах, но точность от этого будет страдать.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Собираю приложение через Usb отладку все окНо когда собираю Apk приложение падает java
Допустим есть программаПри определенном параметре в строке запуска её поведение изменится
У меня есть Skullstxt документ, мне нужно читать его на компьютере а не на сайте