看了微信紅包的算法實現探討(基於PHP)一文,我嘗試使用C++重現,代碼以下:ios
#include <iostream> #include <cstdlib> #include <ctime> int Random(int _max) { _max = _max > 0 ? _max : 1; static bool begin = false; if (!begin) { srand((unsigned)time(nullptr)); //用於保證是隨機數 begin = true; } return rand() % _max; //用rand產生隨機數並設定範圍 } int main() { using namespace std; double total_money = 10; int total_people = 8; double min_money = 0.01; double *per_money = new double[total_people]; for (int i = 0; i < total_people - 1; i++) { double safe = (total_money - (total_people - i)*min_money) / (total_people - i); double var_money = min_money + (double)Random((int)safe * 100) / 100; per_money[i] = var_money; total_money -= var_money; } per_money[total_people - 1] = total_money; for (int i = 0; i < total_people; i++) { cout << i << ": " << per_money[i] << endl; } delete[] per_money; return 0; }
程序運行效果不太理想,最後一個紅包金錢額數老是5~10倍於其它紅包,這是因爲C++提供的隨機函數是均勻分佈的。運行效果:共10元,8個紅包,分配爲0.4九、0.2四、0.0一、0.3一、0.6四、1.3三、1.二、5.78。算法
在網上查找到這一篇微信紅包算法探討,對代碼從新封裝以下,運行效果不錯:segmentfault
random.h微信
#ifndef MY_RANDOM_H #define MY_RANDOM_H #include <cstdlib> #include <ctime> namespace keyven { int rand() { static bool begin = false; if (!begin) { srand((unsigned)time(nullptr)); //用於保證是隨機數 begin = true; } return std::rand(); //用rand產生隨機數並設定範圍 } } #endif
money.h架構
#ifndef MY_MONEY_H #define MY_MONEY_H #include "random.h" #include <cmath> #include <vector> #define TWO_PI 6.2831853071795864769252866 namespace danye_me { double generateGaussianNoise(const double mu, const double sigma) { static bool haveSpare = false; static double rand1, rand2; if (haveSpare) { haveSpare = false; return (sigma * sqrt(rand1) * sin(rand2)) + mu; } haveSpare = true; rand1 = keyven::rand() / ((double)RAND_MAX); if (rand1 < 1e-100) rand1 = 1e-100; rand1 = -2 * log(rand1); rand2 = (keyven::rand() / ((double)RAND_MAX)) * TWO_PI; return (sigma * sqrt(rand1) * cos(rand2)) + mu; } std::vector<double> generateMoneyVector(const double mon, const int pics) { std::vector<double> valueVec; double moneyLeft = mon - pics * 0.01; double mu, sigma; double noiseValue; double TempSum = 0; for (int i = 0; i < pics - 1; i++) { mu = moneyLeft / (pics - i); sigma = mu / 2; noiseValue = generateGaussianNoise(mu, sigma); if (noiseValue < 0) noiseValue = 0; if (noiseValue > moneyLeft) noiseValue = moneyLeft; valueVec.push_back((int)((noiseValue + 0.01) * 100) / (double)100); TempSum += (int)((noiseValue + 0.01) * 100) / (double)100; moneyLeft -= noiseValue; } valueVec.push_back(mon - TempSum); return valueVec; } } #endif
main.cppdom
#include "money.h" #include <iostream> #include <iomanip> int main() { double total_money = 10.8; int people = 7; double Test_Sum = 0; std::vector<double> packets = danye_me::generateMoneyVector(total_money, people); for (std::vector<double>::iterator it = packets.begin(); it != packets.end(); it++) { std::cout << std::setprecision(2) << std::setiosflags(std::ios::fixed | std::ios::showpoint) << *it << std::endl; Test_Sum += *it; } std::cout << "Sum: " << Test_Sum << std::endl; system("pause"); return 0; }
運行效果:共10.8元,7個紅包,分配爲0.8七、1.5三、1.90、1.9二、2.2五、0.7九、1.54。函數
有興趣能夠再看看這篇:微信紅包的架構設計簡介。spa
微信紅包算法探討設計