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>
http://websong.gitee.io/songyublog/