2016-06-10 93 views
0

我有一組小數位數不等的雙打。我需要獲取這些值的SUM(),然後將它們全部歸一化,以使它們SUM()爲1.此外,我有一個要求,即在最終結果中,我們將小數位數限制爲4。我曾嘗試執行以下操作:使用Double的標準化

normalizationFactor = 1/sumOfAllDoublesInGroup; 

for(Object myObject : myGroupOfObjects){ 
    myObject.setDoubleValue = round(myObject.getDoubleValue * normalizationFactor),4); 
} 

private Double round (Double doubleValue, Integer decimalPlaces) { 
    if (places < 0) throw new IllegalArgumentException(); 

    BigDecimal bd = new BigDecimal(value); 
    bd = bd.setScale(places, RoundingMode.HALF_UP); 
    return bd.doubleValue(); 
} 

這裏的缺點是,四捨五入後,我仍然不能保證所有的雙打的SUM()仍然是== 1,我將不勝感激一些幫助這一點。

要清楚的唯一要求是

1)我得到了一組數字,每一個具有不同的小數位數。 2)當所有的說法和完成時,每個數字被限制在4個小數位。 3)組中所有數字的最終SUM()必須恰好= 1

+0

您是不是指'decimalPlaces'而不是'places'?您將不得不對該組數字進行兩次傳球。或者,您將不得不從一個數字中加上或減去0.0001,以使總和等於1。 –

+0

如果您確切需要1,您可能會得到一個數字作爲1減去另一個數字的總和。但是由於double的二元性質,在一般情況下精確的小數精度將不會被滿足 –

回答

0

在double和BigDecimal之間的代碼中有很多轉換。這些轉換可能會爲您的值添加雙精度錯誤。請找到下面的代碼,所有的數字都存儲在BigDecimal中。

List<BigDecimal> myGroupOfObjects = new ArrayList<>(); 
    myGroupOfObjects.add(new BigDecimal("0.3")); 
    myGroupOfObjects.add(new BigDecimal("0.1")); 
    myGroupOfObjects.add(new BigDecimal("0.2")); 
    myGroupOfObjects.add(new BigDecimal("0.2")); 

    BigDecimal sumOfAllDoublesInGroup = new BigDecimal("0.8"); // #HardCoding 

    BigDecimal normalizationFactor = new BigDecimal("1.0") 
     .divide(sumOfAllDoublesInGroup); 

    BigDecimal result = new BigDecimal(0); 
    for(BigDecimal myObject : myGroupOfObjects){ 
     myObject = myObject.multiply(normalizationFactor) 
       .setScale(4, RoundingMode.HALF_UP); 

     result = result.add(myObject); 
    } 

Result: 
0.3750 
0.1250 
0.2500 
0.2500 
------ 
1.0