2

在我的课堂上,我们被分配了一个问题来创建一个“分解器”应用程序,该应用程序计算任何数字的素数分解,直到一个非常大的数字。他给了我们一个Number.java类,用于计算数字是否为素数,以供显而易见的用途。

// Number.java
public class Number {  
    long n;
    public Number(long number) {
        n = number;
    }
    boolean isPrime() {
        for(long k = 2; k < n; k++) {
          if(n % k == 0) return false;
        }
        return true;
    }
}

唯一的问题是这个Number.java类是它有一个构造函数,在我看来这使得它在这种情况下不那么“移动”。我的意思是,在我计算参数的主要因素的循环中,一个新的 Number 对象被一遍又一遍地创建。private Number isPrimeFactor = new Number()在顶部定义 a 而不是Number isPrimeFactor = new Number(i)为循环的每次重复都创建一个新的不是更有意义吗?我问过我的老师,但他并没有真正回答。这是我正在谈论的一些示例代码。

while (remainder!=0 && j<n) {
        Number isFactor = new Number(j);
        if(isFactor.isPrime() && remainder%j==0) {
            remainder = remainder / j;
            factor[i]=j;
            temp = (int) j;
            multiplicity[temp] = multiplicity[temp]+1;
            i++;
        } else {
            j++;
        }
    }
4

6 回答 6

2

是的,new这是相当昂贵的,这意味着调用几千次isPrimeFactor = new Number(j)的效率低于只有一个实例Number并使用 a 更改关联nisPrimeFactor.setN(j)。这是因为new分配了新内存,并且一旦实例不再可访问,垃圾收集器会不时释放内存。

但是,使 Number 不可变的优点是,您不会冒险让一段代码更改其值,而另一段代码认为它没有改变(例如,当您使用线程时这是非常好的属性)。

顺便说一句,我认为Number你教授的课程是一个糟糕的面向对象设计,可变与否。

于 2013-03-14T15:31:33.020 回答
1

这里有意义的是没有一个构造函数,其唯一目的是传递nisPrime():这就是函数参数的用途!

public class PrimeChecker {     
  public static boolean isPrime(long n) {
    for(long k = 2; k * k < n; k++) {
      if(n % k == 0) return false;
    }
    return true;
  }
}
于 2013-03-14T15:33:18.537 回答
0

在内存/速度/代码可读性/维护之间总是有一个选择。因此,不可能以客观的方式回答这个问题。

这个解决方案效率低吗?也许,但话又说回来,函数调用很昂贵,因此任何涉及函数调用的解决方案都可能被标记为低效。

如果这是家庭作业或学习练习,那么代码效率并不是很重要,但编写清晰的代码来解释所涉及的概念非常重要!

附言。

我见过的大多数检查素数的代码都有一个方法“isPrime”,它接受一个数字/整数作为参数。

于 2013-03-14T15:29:41.943 回答
0

除了其他优化之外,没有理由为这些创建数字、整数等。您可以通过以下方式跳过上述所有内容:

public static boolean isPrime(long number) {
    for(long k = 2; k < n; k++) {
      if(n % k == 0) return false;
    }
    return true;
}
于 2013-03-14T15:32:48.983 回答
0

只实例化一次数字并重复分配其字段肯定会更快。但是,在这种情况下,测试isPrime可能是瓶颈,因此您几乎不会注意到差异。

于 2013-03-14T15:33:06.160 回答
-2

你是对的,在循环内分配对象是一种性能反模式。相反,您可以通过使用静态类成员来提高执行速度并提高内存使用率。

// Number.java
public class Number {  
  private static long n;
 public static void setNumber(long number){
        n = number;
 }
 static boolean isPrime() {
     for(long k = 2; k < n; k++) {
       if(n % k == 0) return false;
     }
     return true;
 }
}
于 2013-03-14T15:29:43.760 回答