2016-06-10 109 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