Деление лонгов, возвращаемых методом-неправильные значения
У меня есть два метода: степенной и факториальный:
public static long pow(int x, int n) {
long p = x;
for (int i = 1; i < n; i++) {
p *= x;
}
return p;
}
public static long fact(int n) {
long s = n;
for (int i = 1; i < n; i++ ) {
s *= i;
}
return s;
}
Которые возвращают лонги. Когда я хочу использовать их в новом методе оценки экспоненциальной функции , я получаю неправильные результаты по сравнению с математикой.exp (x). Мой код:
public static void exp(int x, double eps) {
int i = 1;
double pow = 1.0;
double fact = 1.0;
double sum = 0.0;
double temp;
do {
temp = pow/fact;
sum += temp;
pow = pow(x, i);
fact = fact(i);
i++;
}
while (temp > eps);
System.out.println("Check: " + Math.exp(x));
System.out.println("My: " + sum);
}
public static void main() {
int x = 10;
double eps = 0.0000000000001;
exp(x, eps);
}
И выход для x=10:
Проверка: 22026.465794806718
Мой: 21798.734894914145
Чем больше x, тем больше "потеря точности" (не совсем, потому что вы не можете действительно назвать это точный...).
Поворот, когда методыpower иfactorial возвращаютdouble , то выход правильный. Кто-нибудь может объяснить мне, как заставить его работать?
Методыpow иfact должны возвращаться долго, и я должен использовать их вexp (College assignment).
3 ответа:
Если вы попробуете этот метод pow:
public static long pow(int x, int n) { long p = x; System.out.println("Pow: "+x+","+n); for (int i = 1; i < n; i++) { p *= x; System.out.println(p); } return p; }Вы получаете такой результат:
... Pow: 10,20 100 1000 10000 ... ... 1000000000000000 10000000000000000 100000000000000000 1000000000000000000 -8446744073709551616 7766279631452241920Длинное значение переполняется:
10^20слишком велико, чтобы поместиться в длинное.Методыpow иfact должны возвращаться долго, и я должен использовать их вexp (College assignment).
Тогда вы мало что можете сделать, чтобы исправить это. Вы можете создать исключение, если
epsслишком мал.
Насколько велик типичный размер
x? Это может быть целочисленное переполнение. Попробуйте изменить все аргументыintвpowиfactнаlong.
Длинные типы данных не могут обрабатывать десятичную точность, поэтому вы ошибаетесь с длинными значениями. Почему бы просто не заставить функции возвращать двойные значения?
Edit: Вот что я придумал:
public static long pow(int x, int n) { double p = x; for (int i = 1; i < n; i++) { p *= x; } return (long)p; } public static long fact(int n) { double s = n; for (int i = 1; i < n; i++ ) { s *= i; } return (long)s; } public static void exp(int x, double eps) { double pow = 1.0; double fact = 1.0; double sum = 0.0; double temp; for(int ii=1; ii < 100; ii++) { pow = pow(x, ii); fact = fact(ii); temp = (double)pow/(double)fact; temp = temp == 1 ? 0 : temp; sum += temp; } System.out.println("Check: " + Math.exp(x)); System.out.println("My: " + sum); } public static void main(final String[] args) { int x = 10; double eps = 0.0000000000001; exp(x, eps); }Это самое близкое, что вы можете получить, не используя десятичные дроби.
Check: 22026.465794806718 My: 21946.785573087538