Java篇:WeChat 模仿微信紅包的核心遞迴演算法
阿新 • • 發佈:2018-12-18
模仿WeChat的拼手氣紅包 ,例如:10000元傳送50個包。
這50個紅包隨機分配,但是最後相加等於10000.
採用隨機數,隨機紅包金額。
又制定規則,不斷地遞迴運算。
限制最小的紅包金額,例如:0.01,因為考慮人性化,最小的紅包不能是0.
不限制可發出的紅包總額。
但是要限制可得到的最大紅包額度,比如:拼手氣可得到的最大的紅包為紅包總額的60%,剩下的40%由其他人分配。
因為Java的基礎資料型別限制,採用擴大100倍的方式,最後得到的金額除以100.
package com.hc.money; import java.util.ArrayList; import java.util.List; public class Money { // 最小紅包額度 private static final int MINMONEY = 1;// 0.01 // 每個紅包最大是平均值的倍數 private static final double TIMES = 2.1; public static void main(String[] args) { double send = 111.11;// 紅包總額 int sendcount = 43;// 數量 List<Integer> Integers = sendMoney((int) (send * 100), sendcount);// 紅包擴100倍 long l = 0; for (Integer integer : Integers) { l += integer; System.out.println(integer * 1.0 / 100); } System.out.println(l * 1.0 / 100);// 丟失精度 } /** * 拆分紅包 * * @param money * @param count * @return */ public static List<Integer> sendMoney(int money, int count) { // 最大紅包額度 微信隨機紅包最大為200 為所發紅包一半 int MAXMONEY = money / 2; List<Integer> list = new ArrayList<>(); if (!isRight(MAXMONEY, money, count)) {// 驗證 list.add(money); return list;// 不符合規則,則返回總數 } // 紅包最大金額為平均金額的TIMES倍 int max = (int) (money * TIMES / count); max = max > MAXMONEY ? MAXMONEY : max; for (int i = 0; i < count; i++) { int one = random(MAXMONEY, money, MINMONEY, max, count - i); list.add(one); // 除以100,轉換成需要的數目 money -= one;// 紅包總額減去生成的紅包 } return list; } /** * 隨機紅包額度 * * @param money * @param minS * @param maxS * @param count * @return */ private static int random(int MAXMONEY, int money, int minS, int maxS, int count) { // 紅包數量為1,直接返回金額 if (count == 1) { return money; } // 如果最大金額和最小金額相等,直接返回金額 if (minS == maxS) { return minS; } int max = maxS > money ? money : maxS; // 隨機產生一個紅包 int one = ((int) Math.rint(Math.random() * (max - minS) + minS)) % max + 1; int money1 = money - one; // 判斷該種分配方案是否正確 if (isRight(MAXMONEY, money1, count - 1)) { return one; } else { double avg = money1 / (count - 1); if (avg < MINMONEY) { // 遞迴呼叫,修改紅包最大金額 return random(MAXMONEY, money, minS, one, count); } else if (avg > MAXMONEY) { // 遞迴呼叫,修改紅包最小金額 return random(MAXMONEY, money, one, maxS, count); } } return one; } /** * 此種紅包是否合法 * * @param money * @param count * @return */ private static boolean isRight(int MAXMONEY, int money, int count) { double avg = money / count; if (avg < MINMONEY) { return false; } if (avg > MAXMONEY) { return false; } return true; } // String one =Math.random() * 100+""; // String two=one.substring(0,one.lastIndexOf(".")+3); // Math.random()= 0.5346774447849648 // Math.rint 四捨五入 // if (integer.length() > 2) { // integer = integer.substring(0, integer.length() - 2) + "." + // integer.substring(integer.length() - 2); // } else if (integer.length() == 2) { // integer = "0." + integer; // } else if (integer.length() == 1) { // integer = "0.0" + integer; // } }
如果隨機出不符合規則的紅包,則放棄,繼續遞迴運算。
最後的一個紅包就是剩下的金額。
隨機出適合的紅包後,放進紅包list集合中,修改獎池中剩餘的金額,需要格外注意資料的精度,最後展示出來。