All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.handyplus.lib.util.ProbabilityUtil Maven / Gradle / Ivy

The newest version!
package cn.handyplus.lib.util;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 概率工具类
 *
 * @author handy
 */
public class ProbabilityUtil {
    private final Random random = new Random();
    private final List probabilityNumList = new ArrayList<>();

    private ProbabilityUtil() {
    }

    /**
     * 获取实例
     *
     * @return 实例
     */
    public static ProbabilityUtil getInstance() {
        return ProbabilityUtil.SingletonHolder.INSTANCE;
    }

    /**
     * 不加锁进行概率抽取
     *
     * @param num 概率数字 0.1 就表示十分之一概率为true
     * @return true 抽到
     * @since 1.4.0
     */
    public boolean pickIndex(double num) {
        if (num == 0) {
            return false;
        }
        BigDecimal rate = BigDecimal.ONE.divide(new BigDecimal(num + ""), RoundingMode.UP);
        return pickIndex(1, rate.intValue());
    }

    /**
     * 不加锁进行概率抽取
     *
     * @param num    概率数字
     * @param maxNum 总概率
     * @return true 抽到
     */
    public boolean pickIndex(int num, int maxNum) {
        if (num >= maxNum) {
            num = maxNum;
        }
        int[] nums = {num, maxNum - num};
        return randomIndex(nums) == 0;
    }

    /**
     * 加锁进行概率抽取
     *
     * @param num 概率数字
     * @return true 抽到
     * @since 1.4.0
     */
    public synchronized boolean pickSyncIndex(double num) {
        return pickIndex(num);
    }

    /**
     * 加锁进行概率抽取
     *
     * @param num    概率数字
     * @param maxNum 总概率
     * @return true 抽到
     */
    public synchronized boolean pickSyncIndex(int num, int maxNum) {
        return pickIndex(num, maxNum);
    }

    /**
     * 进行二分查询
     *
     * @param nums 数组
     * @return 返回0为匹配到了数组第一个数
     */
    private int randomIndex(int[] nums) {
        probabilityNumList.clear();
        int tot = 0;
        for (int num : nums) {
            tot += num;
            probabilityNumList.add(tot);
        }
        int randomNum = random.nextInt(tot);
        int hi = probabilityNumList.size() - 1;
        int lo = 0;
        while (lo != hi) {
            int mid = (lo + hi) / 2;
            if (randomNum >= probabilityNumList.get(mid)) {
                lo = mid + 1;
            } else {
                hi = mid;
            }
        }
        return lo;
    }

    private static class SingletonHolder {
        private static final ProbabilityUtil INSTANCE = new ProbabilityUtil();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy