Introduction: As we all know, many companies usually conduct performance reviews at the middle/end of the year. Let’s assume that the performance scores are A, B, C and D from high to low. Then, because the performance appraisal result is directly related to an employee’s promotion and salary increase and year-end bonus payment standard (for example: the monthly salary of 3 months for GRADE A; 2.5-month monthly salary for grade B; Grade C will receive monthly salary of 2 months; D grades don’t get annual bonuses and risk being fired), so company executives have an unwritten rule for performance reviews that implicitly and in advance assigns A percentage of each grade (e.g., A 10%; B 20%; C 65%; D) 5%. So now the problem comes. In a project team, except for a few excellent employees, the work of others is almost the same, and there will be opinions on who is given higher and who is given lower. If you are the leader of the project team at this time, how should you conduct performance appraisal so as to balance the opinions of senior executives and team members as much as possible?

Yes, since it’s hard to choose, then write code to implement a random selection algorithm with weights, good luck will draw a good performance, bad luck will get a low performance. The algorithm is open and transparent, and the performance is one item for luck. One item for everyone: ◔ plus-one ◔

Algorithm implementation

Before we write the actual code, we can think about how to implement this random selection with weights.

To use the example above: A has A 10% chance of appearing, B has A 20% chance, C has A 65% chance, and D has A 5% chance. Let’s convert this to a progressive probability value, which looks like this:

Algorithm thinking has been clear, algorithm logic is easy to write, I will give you an example of the algorithm I wrote, for reference.

import org.junit.Test;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Random;

/** * select ** randomly with weights@author zifangsky
 * @date 2020/5/15
 * @since1.0.0 * /
public class Problem_004_Weight_Random {

    /** * test code */
    @Test
    public void testMethods(a){
        Item[] items = new Item[]{new Item("A".0.1),
                new Item("B".0.2),
                new Item("C".0.65),
                new Item("D".0.05),};

        WeightRandom weightRandom = new WeightRandom(items);
        for(int i = 0; i < 10; i++){
            System.out.println(MessageFormat.format("Performance score of employee {0} : {1}",
                    (i + 1),weightRandom.nextItem())); }}/** * random selection with weights */
    static class WeightRandom{
        /** * option array */
        private Item[] options;

        /** * The critical value of weight */
        private BigDecimal[] criticalWeight;

        private Random rnd;

        public WeightRandom(Item[] options) {
            if(options == null || options.length < 1) {throw new IllegalArgumentException("Exception in option array!");
            }
            this.options = options;
            this.rnd = new Random();
            / / initialization
            this.init();
        }

        /** ** random function */
        public String nextItem(a){
            double randomValue = this.rnd.nextDouble();
            // Find the range of random values
            int index = this.searchIndex(randomValue);

            return this.options[index].getName();
        }

        /** * find the range of random values */
        private int searchIndex(double randomValue){
            BigDecimal rndValue = new BigDecimal(randomValue);
            int high = this.criticalWeight.length - 1;
            int low = 0;
            int median = (high + low) / 2;

            BigDecimal medianValue = null;
            while(median ! = low && median ! = high){ medianValue =this.criticalWeight[median];

                if(rndValue.compareTo(medianValue) == 0) {return median;
                }else if(rndValue.compareTo(medianValue) > 0){
                    low = median;
                    median = (high + low) / 2;
                }else{
                    high = median;
                    median = (high + low) / 2; }}return median;
        }

        /** * initializes */
        private void init(a){
            / / total weight
            BigDecimal sumWeights = BigDecimal.ZERO;
            // The threshold of the weight
            this.criticalWeight = new BigDecimal[this.options.length + 1];

            //1. Calculate the total weight
            for(Item item : this.options){
                sumWeights = sumWeights.add(new BigDecimal(item.getWeight()));
            }

            //2. Calculate the threshold for each option
            BigDecimal tmpSum = BigDecimal.ZERO;
            this.criticalWeight[0] = tmpSum;
            for(int i = 0; i < this.options.length; i++){
                tmpSum = tmpSum.add(new BigDecimal(this.options[i].getWeight()));
                this.criticalWeight[i + 1] = tmpSum.divide(sumWeights, 2, BigDecimal.ROUND_HALF_UP); }}}/** * requires a random item */
    static class Item{
        /** * name */
        private String name;
        /** ** weight */
        private double weight;

        public Item(String name, double weight) {
            this.name = name;
            this.weight = weight;
        }

        public String getName(a) {
            return name;
        }

        public double getWeight(a) {
            returnweight; }}}Copy the code

Sample code output is as follows:

Employee 1's performance score: C Employee 2's performance score: B Employee 3's performance score: B Employee 4's performance score: C Employee 5's performance score: C Employee 6's performance score: B Employee 7's performance score: C Employee 8's performance score: C Employee 9's performance score: B Employee 10's performance score: CCopy the code