Деление длинных, которые возвращаются методом - неправильные значения - PullRequest
3 голосов
/ 01 ноября 2011

У меня есть два метода: мощность и факториал:

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;
}

которые возвращают longs . Когда я хочу использовать их в новом методе оценки Экспоненциальная функция , я получаю неправильные результаты по сравнению с Math.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);
}

и вывод для х = 10:

Проверка: 22026.465794806718

My: 21798.734894914145

чем больше х, тем больше «потеря точности» (не совсем так, потому что вы не можете назвать ее точной ...).

Поворот заключается в том, что когда методы power и factorial return double , тогда выходной сигнал правильный. Может кто-нибудь объяснить мне, как заставить это работать?

Методы pow и факт должны возвращаться долго, и я должен использовать их в exp (задание колледжа).

Ответы [ 3 ]

3 голосов
/ 01 ноября 2011

Если вы попробуете этот метод 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 (задание колледжа).

Тогда не так много, что вы можете сделать, чтобы это исправить. Вы можете выдать исключение, если eps слишком мало.

0 голосов
/ 01 ноября 2011

Какого размера обычно x?Это может быть целочисленное переполнение.Попробуйте изменить все int аргументы в pow и fact на long.

0 голосов
/ 01 ноября 2011

Типы данных long не могут обрабатывать десятичную точность, поэтому ваши значения неверны с long.Почему у вас просто нет функций, возвращающих двойные значения?

Редактировать: Вот то, что я придумал:

  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
...