I need to round BigDecimal numbers according to the Largest Remainder Method (LRM). Please reference this SO post with this answer. Here's my version of the algorithm in Java:

public class LargestRemainderMethod {

    public static List<BigDecimal> roundValues(List<BigDecimal> values, int roundTo, BigDecimal desiredSum) {
        // 1. Sort by largest remainder
        values.sort((d1, d2) ->

        // 2. Rounding everything down
        List<BigDecimal> roundedValues = new ArrayList<BigDecimal>(values.size());
        for (BigDecimal value : values) {
            roundedValues.add(value.setScale(roundTo, RoundingMode.DOWN));

        // 3. Now round up values until desired sum is achieved or we have
        //    no other values to round up
        for (int i = 0; i < values.size(); i++) {

            BigDecimal roundedSum = roundedValues.stream().reduce(BigDecimal.ZERO, BigDecimal::add);

            if (roundedSum.compareTo(desiredSum) != 0) {
                roundedValues.set(i, values.get(i).setScale(roundTo, RoundingMode.UP));
        return roundedValues;

I apply LRM to a list of objects with a BigDecimal value. For example:

List<BigDecimal> fractionsOfOwnership = 

List<BigDecimal> roundedValues = LargestRemainderMethod.roundValues(fractionsOfOwnership, 1, new BigDecimal("1.0"));

Next, for each owner, I need overwrite the original fractionOfOwnership with the corresponding rounded value determined by the LRM roundedValues method.

Currently, I sort the owners as I know they'll be sorted in LargestRemainderMethod.roundValues. Then, I iterate through the owners list setting the rounded values using the same index.

owners.sort((o1, o2) ->
for (int i = 0; i < owners.length; i++) {

But this violates DRY. How can this be improved such that I'm not duplicating code?


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.