Java – randomly divide a given number m into N parts

Therefore, the idea I have is to be able to divide $2.00 into 10 people, and each person will receive a random amount of $x.xx (N and m will always be limited to 2 decimal places and less than 0)

Example: {0.12,0.24,1.03,0.01,0.2,0.04,0.11,0.18,0.05,0.02}

At present, I have tried:

private static BigDecimal[] randSum(int n,double m)
{
    Random rand = new Random();
    BigDecimal randNums[] = new BigDecimal[n],sum = new BigDecimal(0).setScale(2);

    for (int i = 0; i < randNums.length; i++)
    {
        randNums[i] = new BigDecimal(rand.nextDouble()).setScale(2,RoundingMode.HALF_EVEN);
        sum = sum.add(randNums[i]);
    }

    for (int i = 0; i < randNums.length; i++)
    {
        BigDecimal temp1 = randNums[i].divide(sum,2,RoundingMode.HALF_EVEN);
        BigDecimal temp2 = temp1.multiply(new BigDecimal(m).setScale(2));
        randNums[i] = temp2;
    }

    return randNums;
}

public static void main(String[] args)
{
    BigDecimal d[] = randSum(5,2);

    double sum = 0;
    for (BigDecimal n : d)
    {
        sum += n.doubleValue();
        System.out.println(n);
    }
    System.out.println("total: " + sum);
}

But bigdecimals were so chaotic that they didn't add up Sometimes the total is 1.98 or 2.01 Doubles does not work because of double precision floating point numbers

Code from:

Getting N random numbers that the sum is M

Solution

Suppose you need a fixed precision (passed as a prec parameter):

static public BigDecimal[] split(BigDecimal sum,int prec,int count) {
    int s = sum.scaleByPowerOfTen(prec).intValue();
    Random r = new Random();
    BigDecimal[] result = new BigDecimal[count];
    int[] v = new int[count];

    for (int i = 0; i < count - 1; i++)
       v[i] = r.nextInt(s);
    v[count - 1] = s;

    Arrays.sort(v);
    result[0] = BigDecimal.valueOf(v[0]).scaleByPowerOfTen(-prec);
    for (int i = 1; i < count; i++)
       result[i] = BigDecimal.valueOf(v[i] - v[i - 1]).scaleByPowerOfTen(-prec);
    return result;
}

This method uses random Nextint() evenly distributed attribute After sorting, the value of v [] array is the point where the whole amount is split, so you can use the difference between adjacent elements to generate results:

[   2,5,10,11,...,197,200]  // v[]
[0.02,0.03,0.03]  // result[]

Here, you operate with integer values, so the rounding problem is no longer bothered

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>