js红包算法【转载】

源文地址:https://juejin.im/post/5ae413946fb9a07a9c03f7f7

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        class RandomSplit {
            constructor(num) {
                // 实际总数
                this.num = this.getNum(num);
                // 放大倍数
                try {
                    this.multiple = this.num.toString().split('.')[1].length;
                } catch (e) {
                    this.multiple = 0;
                }
                // 用于整数运算的总数
                this.calcNum = this.num * Math.pow(10, this.multiple);
            }
            // 判断是否为number(取用至“is-number”)
            isNumber(num) {
                let number = +num;
                if ((number - number) !== 0) {
                    return false;
                }
                if (number === num) {
                    return true;
                }
                if (typeof num === 'string') {
                    if (number === 0 && num.trim() === '') {
                        return false;
                    }
                    return true;
                }
                return false;
            }
            // 获取数字
            getNum(num, defaultNum = 0) {
                return this.isNumber(num) ? (+num) : defaultNum;
            }
            //均分份数, 均分精度, 是否直接返回放大后的整数
            average(n, precision, isInt) {
                precision = Math.floor(this.getNum(precision, 0));
                n = Math.floor(this.getNum(n));
                let calcNum = this.calcNum * Math.pow(10, precision < 0 ? 0 : precision);
                // 份数超过放大后的计算总数,即不够分的情况
                if (n > calcNum) {
                    return [];
                } else {
                    let index = 0;
                    // 平均数
                    let avg = Math.floor(calcNum / n);
                    // 剩余数
                    let rest = calcNum % n;
                    // 剩余数填充间隔
                    let gap = Math.round((n - rest) / rest) + 1;
                    // 原始平均数组
                    let result = Array(n).fill(avg);
                    // 
                    while (rest > 0) {
                        index = (--rest) * gap;
                        result[index >= n ? (n - 1) : index]++;
                    }
                    // 返回放大后的结果数组
                    if (isInt) {
                        return result;
                    }
                    // 返回处理完符合精度要求的结果数组
                    return result.map((item) => {
                        return (item / Math.pow(10, this.multiple + precision));
                    });
                }
            }
            // 随机划分的份数, 划分精度
            split(n, precision) {
                n = Math.floor(this.getNum(n));
                precision = Math.floor(this.getNum(precision, 0));
                // 均分
                let arr = this.average(n, precision, true);
                let arrResult = arr.concat();
                for (let i = 0; i < arr.length; i++) {
                    //给出的总额
                    let num = Math.floor(Math.random() * arr[i]);
                    // 给左邻的数额
                    let numLeft = Math.floor(Math.random() * num);
                    // 给右邻的数额
                    let numRight = num - numLeft;
                    // 首尾index处理
                    let iLeft = i === 0 ? (arr.length - 1) : (i - 1);
                    let iRight = i === (arr.length - 1) ? 0 : (i + 1);
                    arrResult[i] -= num;
                    arrResult[iLeft] += numLeft;
                    arrResult[iRight] += numRight;
                }
                // 缩小至原尺度
                return arrResult.map((item) => {
                    return (item / Math.pow(10, this.multiple + precision));
                });
            }
        }
        var r = new RandomSplit(250);
        console.log(r.average(3))
        console.log(r.split(3))
    </script>
</body>

</html>

  

posted @ 2018-05-03 16:05  宋宇  阅读(295)  评论(0编辑  收藏  举报