Generate n random numbers whose sum is m and all numbers should be greater than zero

后端 未结 8 831
忘掉有多难
忘掉有多难 2020-12-18 04:04

I want to generate 9 non zero random numbers whose sum is 250. I have tried following code it gives me 9 random numbers but some numbers are zero.

 public vo         


        
相关标签:
8条回答
  • 2020-12-18 04:37

    Here's one way to do it, that avoids (most) magic numbers and provides a decent distribution of numbers though all will be smaller than other possible solutions.

    public static void n_random(int count, int finalSum)
    {
        Random r = new Random();
        int numbers[] = new int[count];
        int sum = 0;
        for (int i = 0; i < count - 1; i++)
        {
            numbers[i] = r.nextInt((finalSum - sum) / 2) + 1;
            sum += numbers[i];
        }
        numbers[count - 1] = finalSum - sum;
    
        StringBuilder numbersString = new StringBuilder("Random number list: ");
        for (int i = 0; i < count; i++)
            numbersString.append(numbers[i] + " ");
        System.out.println(numbersString);
    }
    
    public static void main(String[] args)
    {
        n_random(9, 250);
    }
    
    0 讨论(0)
  • 2020-12-18 04:40

    this is javascript alternative

    function getRandomNos(m,n) {
    
        var nums=[];
        var i;
    
        for (i = 0;i<n;i++) {
           nums[i] = Math.random();
        }
        var factor = (m-n) / nums.reduce(add, 0);
        for (i = 0;i<nums.length;i++) {
           nums[i] = parseInt(nums[i] * factor) + 1;
        }
    
        var fudge = m - nums.reduce(add, 0);
    
        for (i=0;i<fudge;i++) {
           nums[i] = nums[i] + 1;
        }
        console.log(nums);
        console.log(nums.reduce(add, 0));
    
    }
    
    function add(a, b) {
        return a + b;
    }
    
    0 讨论(0)
  • 2020-12-18 04:42

    Your code line:

    r.nextInt(250 - sum);
    

    ... will generate a pseudo-random from 0 (included) to 250 - sum (excluded).

    See API for Random.nextInt.

    I won't try to solve all your problem here, but simply adding 1 to the expression above would guarantee that it never returns 0.

    All remaining adaptations up to you though :)

    For instance if 250 - sum - 1 evaluates to negative, then you'll throw an IllegalArgumentException.

    0 讨论(0)
  • 2020-12-18 04:50
    //Perl code translated to Java
    //Its working and no 0's !!!!
    
    import java.util.*;
    import java.util.stream.*;enter code here
    
    public class MyClass {
        public static void main(String args[]) {
         int numberOfDraws = 17;
         int targetSum = 40;
         
    
    
    Random r = new Random();
    
    
    List<Integer> load = new ArrayList<>();
    
    
    
    int sum = 0;
    for (int i = 0; i < numberOfDraws; i++) {
            int next = r.nextInt(targetSum) + 1;
            load.add(next);
            sum += next;
            System.out.println("Arraylist first loop " + load.get(i));
        }
        
        
    double factor = (((double)targetSum)-((double)numberOfDraws)) / ((double)sum);
    System.out.println("Factor value: " + factor);
    
    int newSum =0;
    for (int i = 0; i < numberOfDraws; i++) {
        load.set(i, (int) ((load.get(i) * factor)) + 1);
        newSum += load.get(i);
        
        System.out.println("Arraylist second loop " + load.get(i));
    }
    
    
    
    int fudge = targetSum - newSum;
    for (int i = 0; i < fudge; i++) {
    
       
       int y = r.nextInt(numberOfDraws);
            load.set(i, load.get(i) + 1);
       
    }
    
    System.out.println("Random arraylist " + load);
    
        }
        }
    
    0 讨论(0)
  • 2020-12-18 04:53

    A call to Random.nextInt(n) will return an integer between 0 and n-1

    try temp = r.nextInt(250 - sum) + 1; and see if that solves your issue.

    0 讨论(0)
  • 2020-12-18 04:55

    Generate n random numbers whose sum is m and all numbers should be greater than zero

    The following is basically what you were trying to achieve. Here, it's written in Perl, since I don't know Java well, but it should be easy to translate.

    use strict;
    use warnings;
    use feature qw( say );
    
    use List::Util qw( shuffle );
    
    my $m = 250;
    my $n = 9;
    my @nums;
    while ($n--) {
       my $x = int(rand($m-$n))+1;  # Gen int in 1..($m-$n) inclusive.
       push @nums, $x;
       $m -= $x;
    }
    
    say join ', ', shuffle @nums;   # shuffle reorders if that matters.
    

    The problem with your approach is that you'll end up with a lot of small numbers. Five sample runs with the numbers in ascending order:

    • 1, 1, 1, 1, 2, 3, 6, 50, 185
    • 1, 1, 1, 1, 2, 3, 4, 13, 224
    • 1, 1, 1, 1, 1, 3, 8, 11, 223
    • 1, 1, 1, 1, 2, 4, 19, 103, 118
    • 2, 2, 9, 11, 11, 19, 19, 68, 109

    A better approach might be to take N random numbers, then scale them so their sum reaches M. Implementation:

    use strict;
    use warnings;
    use feature qw( say );
    
    use List::Util qw( sum );
    
    my $m = 250;
    my $n = 9;
    
    # Generate $n numbers between 0 (incl) and 1 (excl).
    my @nums;
    for (1..$n) {
       push @nums, rand();
    }
    
    # We subtract $n because we'll be adding one to each number later.
    my $factor = ($m-$n) / sum(@nums);
    
    for my $i (0..$#nums) {
       $nums[$i] = int($nums[$i] * $factor) + 1;
    }
    
    # Handle loss of fractional component.
    my $fudge = $m - sum(@nums);
    for (1..$fudge) {
       # Adds one to a random number.
       ++$nums[rand(@nums)];
    }
    
    say join('+', @nums), '=', sum(@nums);
    

    Five sample runs:

    32+32+23+42+29+32+29+20+11=250
    31+18+25+16+11+41+37+56+15=250
    21+15+40+46+22+40+32+1+33=250
    34+24+18+29+45+30+19+29+22=250
    3+45+20+6+3+25+18+65+65=250
    
    0 讨论(0)
提交回复
热议问题