划分方法返回的long - 错误的值

时间:2011-11-01 13:44:14

标签: java overflow primitive-types

我有两种方法:power和factorial:

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 。当我想在评估Exponential function的新方法中使用它时,我得到的错误结果与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);
}

,x = 10的输出为:

  

检查:22026.465794806718

     

我:21798.734894914145

x越大,“精度损失越大”(不完全是因为你无法真正称之为精确......)。

扭曲是,当方法 power factorial 返回 double 时,输出是正确的。任何人都可以解释我如何使它工作吗?

方法 pow fact 必须返回很长时间,我必须在 exp (大学作业)中使用它们。

3 个答案:

答案 0 :(得分:3)

如果您尝试使用此方法:

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太小,您可能会抛出异常。

答案 1 :(得分:0)

长数据类型无法处理小数精度,这就是为什么长时间值错误的原因。你为什么不让函数返回double值?

编辑:以下是我的想法:

  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

答案 2 :(得分:0)

x通常有多大?它可能是整数溢出。请尝试将intpow中的所有fact参数更改为long