2015-06-10 85 views
1

我有一些代碼來找出不同數據類型(int,long,double)與BigInteger比較的操作的正確性。操作獲取一個數字的階乘,直到結果與BigInteger相同。將幾種方法合併到一箇中。泛型

問題是我該如何改變我的代碼,使更通用,緊湊和乾淨?我怎麼能得到唯一的方法,而不是4不同類型的? 此方法中的邏輯與流程相同。

代碼(而不比較邏輯)是:

private static HashMap<BigInteger, BigInteger> bigIntegerFactorials = new HashMap<>(); 
private static BigInteger bigIntegerFactorial(BigInteger number) { 
    if (number.equals(BigInteger.ONE)) { 
     return BigInteger.ONE; 
    } 
    BigInteger result = bigIntegerFactorials.get(number); 
    if (result == null) { 
     result = number.multiply(bigIntegerFactorial(number.subtract(BigInteger.ONE))); 
     bigIntegerFactorials.put(number, result); 
    } 
    return result; 
} 

private static HashMap<Integer, Integer> intFactorials = new HashMap<>(); 
private static int intFactorial(int number) { 
    if (number == 1) { 
     return 1; 
    } 
    Integer result = intFactorials.get(number); 
    if (result == null) { 
     result = number * intFactorial(number - 1); 
     intFactorials.put(number, result); 
    } 
    return result; 
} 

private static HashMap<Long, Long> longFactorials = new HashMap<>(); 
private static long longFactorial(long number) { 
    if (number == 1) { 
     return 1L; 
    } 
    Long result = longFactorials.get(number); 
    if (result == null) { 
     result = number * longFactorial(number - 1); 
     longFactorials.put(number, result); 
    } 
    return result; 
} 

private static HashMap<Double, Double> doubleFactorials = new HashMap<>(); 
private static double doubleFactorial(double number) { 
    if (number == 1) { 
     return 1.; 
    } 
    Double result = doubleFactorials.get(number); 
    if (result == null) { 
     result = number * doubleFactorial(number - 1); 
     doubleFactorials.put(number, result); 
    } 
    return result; 
} 

非常感謝提前。

+0

我的建議是看一個case語句(https://docs.oracle.com/javase/tutorial/java /nutsandbolts/switch.html)如果你真的想用一種方法。有時候,具有獨特(和可讀)名稱的不同方法對乾淨代碼是最好的:) – Gorbles

+1

一種選擇是使用'factorial(Number n)',但不能輕鬆寫出這一行'result = number * longFactorial (number - 1);'因爲在Java中沒有操作符重載... – assylias

+0

是否可以使用java 8?如果是的話,那麼你可以通過創建一個接受相應的lambda函數(如乘法)的泛型方法來輕鬆實現這一點,然後爲每種情況指定這些函數。 – user3707125

回答

2

你可以通過乘法和遞減函數的一般方法:

private static Map<Number, Number> factorials = new HashMap<>(); 

private static <T extends Number> T factorial(T n, BinaryOperator<T> multiply, UnaryOperator<T> decrement) { 
    if (n.doubleValue() == 1) return n; 
    T result = (T) factorials.get(n); 
    if (result == null){ 
    result = multiply.apply(n, factorial(decrement.apply(n), multiply, decrement)); 
    factorials.put(n, result); 
    } 
    return result; 
} 

然後你就可以改變你的原始方法如下:

public static int intFactorial(int number) { 
    return factorial(number, (i, j) -> i * j, i -> i - 1); 
} 

警告:這種方法似乎崩潰,但Netbeans的編譯罰款用javac ...

+0

它看起來非常好。我在我的代碼中使用它。運營商非常棒的伎倆。謝謝。 – zds

1

如果你真的想計算一個階乘,那麼doubleBigDoublefactorial only applies to integer values以後就沒有任何需要。而且,既然是這樣,你可以將任何整數類型轉換爲BigInteger,並採用一種方法,其中任何Number返回BigInteger

這是一個測試類

public class Junk { 
    public static void main(String[] args) { 
     long val = 9; 
     Junk j = new Junk(); 
     System.out.println(val + "! = " + j.factorial(val)); 
     BigInteger nine = new BigInteger("9"); 
     System.out.println(nine + "! = " + j.factorial(nine)); 
     short nine_short = 9; 
     System.out.println(nine_short + "! = " + j.factorial(nine_short)); 
    } 

    private HashMap<BigInteger, BigInteger> map = new HashMap<>(); 


    public BigInteger factorial(Number number){ 
     if(1 == number.intValue()){ 
      return BigInteger.ONE; 
     } 

     BigInteger bigInteger = new BigInteger(number.toString()); 
     BigInteger result = map.get(bigInteger); 

     if(result == null){ 
      result = bigInteger.multiply(factorial(bigInteger.subtract(BigInteger.ONE))); 
      map.put(bigInteger,result); 
     } 

     return result; 
    } 
} 

和輸出

9! = 362880 
9! = 362880 
9! = 362880
+0

'BigInteger.ONE.equals(number)'只會在數字是BigInteger時返回true ... – assylias

+0

@assylias Ooops。固定。 – MadConan

+0

@MadConan也許我的問題還不夠清楚,對此抱歉,但想法是展示不同數據類型的選擇階乘的核心。例如,如果我們使用short,我們不能得到9! = 362880,因爲它超出了二進制補碼整數的16位範圍。短暫的結果將會提前失敗。我使用BigInteger總是知道任何階乘的正確結果。我將'bigIntegerFactorials()'的結果與其他人進行比較,我可以看到不同的數據類型失敗的地方。感謝您的回答,但如果任務是找到任何因子,我會採取您的邏輯。 – zds

相關問題