手把手教你写 JS 红包算法,面试、实战一把拿捏!
宝子们!一到过年,微信红包 “咻咻” 发个不停。可你知道这红包金额随机分配的背后,藏着什么神秘代码吗?今天就带大家用 JS 揭开大厂常考的红包算法面纱,学完面试、实战都能派上用场啦~
一、红包算法基础代码,先睹为快!
/**
* 红包
* @param {number} total 总金额
* @param {number} num 红包个数
* @return {number[]} 随机金额数组
*/
function hongbao(total, num) {
const arr = [];
let restAmount = total; // 剩余金额
let restNum = num; // 剩余个数
for (let i = 0; i < num - 1; i++) {
let amount = (Math.random() * (restAmount / restNum * 2)).toFixed(2);
restAmount -= amount;
restNum --;
arr.push(amount);
}
arr.push(restAmount.toFixed(2));
return arr;
}
console.log(hongbao(100, 10));
这段代码就是红包算法的 “雏形” 啦!咱们来逐行拆解:
- 首先定义hongbao函数,接收total(总金额)和num(红包个数)两个参数,目标是返回一个包含每个红包金额的数组。
- 初始化arr数组用来存红包金额,restAmount记录剩余总金额,restNum记录剩余红包个数。
- 进入循环,在倒数第二个红包之前,每次通过Math.random()生成一个随机数,再乘以(restAmount / restNum * 2),最后用toFixed(2)保留两位小数,得到一个红包金额。这里乘以 “人均值的两倍”,是为了让金额有一定随机性,又不会太离谱,是不是很巧妙呀😎?
- 每确定一个红包金额,就从剩余金额和个数里减去,再把金额存到数组中。
- 循环结束后,把最后剩下的金额作为最后一个红包,也存进数组,最后返回结果~
二、等等!这段代码有 “坑”!
虽然上面的代码看起来能跑,但其实暗藏不少问题,在实际应用中可是要 “翻车” 的!
1. 精度误差:钱算不准啦!
JavaScript 里,浮点数计算有个 “老大难” 问题。比如0.1 + 0.2,结果不是0.3,而是0.30000000000000004!咱们的红包算法里,restAmount -= amount;这样的计算,多来几次,最后总金额可能就对不上了😱。这要是发红包少给用户钱,可就麻烦大了!
2. 随机性 “不靠谱”:有人总拿大红包?
现在的算法,随机分配不够科学。有可能连续几个红包都是大金额,后面的人只能捡 “漏”,导致分配不公平。想象一下,你和朋友抢红包,别人都是几十块,你只有几分钱,是不是想 “摔手机”😤?
3. 边界情况没处理:红包金额能为 0?
代码里没保证每个红包至少有0.01元,极端情况下可能出现金额为0的红包,这显然不符合常理。谁发红包会发个空包呀,太 “抠门” 了!
三、优化升级!打造靠谱红包算法
1. 解决精度问题:换个 “姿势” 计算
把金额单位从 “元” 换成 “分”,所有计算都用整数进行,最后再换算回 “元”。这样就能完美避开浮点数精度问题啦~
2. 优化随机性:让红包分配更公平
限制每个红包的最大和最小金额,比如最小0.01元,最大不超过剩余人均金额的2倍,这样就能让金额分布更均匀,大家抢红包都能开心~
3. 处理边界情况:杜绝 “空包”!
在生成红包金额时,强制每个红包至少0.01元(也就是1分),保证每个红包都 “有料”!
优化后的代码来咯:
function hongbao(total, num) {
const totalCent = total * 100; // 转换为分
const minCent = 1; // 最小金额1分
const result = [];
for (let i = 0; i < num - 1; i++) {
// 计算当前红包最大可分配金额
const maxCent = Math.min(totalCent - minCent * (num - i - 1), (totalCent / (num - i)) * 2);
let amountCent = Math.floor(Math.random() * (maxCent - minCent + 1)) + minCent;
result.push(amountCent / 100);
totalCent -= amountCent;
}
result.push(totalCent / 100);
return result;
}
对比之前的代码,新代码多了单位转换、边界限制,还调整了随机范围,是不是严谨多了?
四、总结
红包算法看似简单,实则暗藏玄机,不仅要考虑技术细节,还得融入产品思维,保证用户体验~下次面试遇到红包算法题,或者自己想做个红包小功能,这些知识就能派上用场啦!要是还有疑问,评论区喊我,一起探讨呀~