O Ano Novo Chinês está chegando em breve. Os envelopes vermelhos do WeChat são muito populares durante o Ano Novo Chinês. Recentemente, um projeto também queria pegar envelopes vermelhos, então escrevi um algoritmo de geração de envelopes vermelhos.
Requisitos para o algoritmo de geração de envelopes vermelhos
Pré-crie todos os envelopes vermelhos ou gerar aleatoriamente um envelope vermelho se um pedido
Simplificando, é o processo de decomposição de um grande número inteiro m (diretamente em unidades de "dividir em" unidades, como 1 yuan, ou seja, 100) em n pequenos números. A gama de pequenos números inteiros é [min, max].
A idéia mais simples é garantir a linha de fundo primeiro, cada pequeno envelope vermelho tem min e, em seguida, cada solicitação gera aleatoriamente um número inteiro que varia de 0 a (máximo-min) e depois adicionar min ao dinheiro do envelope vermelho.
Embora esse algoritmo seja simples, ele tem uma desvantagem: os envelopes vermelhos gerados no final podem ser todo o dinheiro min. Em outras palavras, o último envelope vermelho pode ser de 0,01 yuan.
Outra maneira é pré-criar todos os envelopes vermelhos, para que seja mais fácil de controlar. Eu escolhi pré-criar todos os envelopes vermelhos.
Algoritmo de geração de envelope vermelho ideal
O resultado ideal da geração de envelopes vermelhos é que existem mais envelopes vermelhos próximos ao valor médio, e existem relativamente poucos envelopes vermelhos grandes e pequenos envelopes vermelhos.
Como você pode imaginar, a distribuição do número de pacotes vermelhos gerados é um pouco como uma distribuição normal.
Então, como alcançar esse requisito de mais valores próximos à linha média?
É encontrar um algoritmo que possa aumentar a probabilidade em torno da média. Em seguida, use um método de "expansão" e "contração" para alcançar esse efeito.
Se você primeiro quadrado, gerar números aleatórios na faixa quadrada e, em seguida, quadrado, a probabilidade não será mais média.
Algoritmo específico:
classe pública hongbaoalgorithm {estático aleatório = novo aleatório (); estático {RandomSeed (SystemCurrentTimEmillis ()); } public static void main (string [] args) {long max = 200; longo min = 1; LONG [] resultado = Hongbaoalgorithmgenerate (100_0000, 10_000, Max, Min); total longo = 0; for (int i = 0; i <resultadoLength; i ++) {// SystemOutPrintln ("resultado [" + i + "]:" + resultado [i]); // SystememOutPrintln (resultado [i]); total += resultado [i]; } // Verifique se a quantidade total de pacotes vermelhos gerados é correta SystemEmOutPrintln ("Total:" + Total); // Calcule o número de pacotes vermelhos para cada dinheiro e verifique se está próximo da distribuição normal int contagem [] = new int [(int) max + 1]; for (int i = 0; i <resultLength; i ++) {count [(int) resultado [i]]+= 1; } para (int i = 0; i <countLength; i ++) {SystememOutPrintln ("" + i + "" + count [i]); }} /*** produz números aleatórios entre Min e Max, mas a probabilidade não é média e a probabilidade de Min à direção máxima aumenta gradualmente. * Primeiro quadrado, depois gera um número aleatório dentro da faixa de valor quadrado e, em seguida, quadra -o, que produz um efeito de "expansão" e "encolhimento". * * @param min * @param max * @return */ static longo xrandom (min longo, max longo) {return sqrt (nextlong (sqr (max - min))); } / **** @param Total* Quantidade total do envelope vermelha* @param Contagem* Número de envelopes vermelhos* @param max* quantidade máxima de cada pequeno envelope vermelho* @param min* quantidade mínima de cada pequeno envelope vermelho* @return matriz de cada contagem de cada contagem de um pequeno e mais longo) / longo) longo) longo)) média longa = total / contagem; longo a = média - min; longo b = max - min; // // A probabilidade de um número tão aleatório realmente mudou, e a possibilidade de gerar um número grande é menor que a probabilidade de gerar um número decimal. // Isso alcança que a maioria dos envelopes vermelhos tem o valor em torno da média. Existem menos envelopes vermelhos grandes e pequenos envelopes vermelhos. Longo Range1 = Sqr (média - min); Longo Range2 = Sqr (Máx - Média); for (int i = 0; i <resultado de resultado; i ++) {// porque o número de pequenos envelopes vermelhos geralmente é maior que o número de envelopes vermelhos grandes, porque a probabilidade aqui precisa ser alterada. // Quando o valor aleatório> valor médio, um pequeno envelope vermelho é gerado // Quando o número aleatório <valor médio, um grande envelope vermelho é gerado se (próximo (min, max)> média) {// reduz o dinheiro na linha média // temp longo = min + sqrt (nextLong (range1)); longa temp = min + xrandom (min, média); resultado [i] = temp; total -= temp; } else {// Adicione dinheiro na linha média // temp longo = max - sqrt (nextlong (range2)); longa temp = max - xrandom (média, max); resultado [i] = temp; total -= temp; }} // Se ainda houver dinheiro, tente adicioná -lo ao pequeno envelope vermelho. Se não puder ser adicionado, tente o próximo. while (total> 0) {for (int i = 0; i <resultadoLength; i ++) {if (total> 0 && result [i] <max) {resultado [i] ++; total--; }}} // Se o dinheiro for negativo, você precisará retirar o pequeno envelope vermelho gerado enquanto (total <0) {for (int i = 0; i <resultLength; i ++) {if (total <0 && result [i]> min) {resultado [i]-; total ++; }}} Retornar resultado; } estático longo sqrt (longo n) {// aprimorou a pesquisa da tabela? retornar (longo) mathsqrt (n); } estática longa sqr (long n) {// A pesquisa da tabela é rápida ou é calculada diretamente rapidamente? retornar n * n; } estático longo próximo (longo n) {return RandomNextInt ((int) n); } estático longo próximo (Min longo, máximo) {return RandomNextInt ((int) (max - min + 1)) + min; }}Depois de contar os resultados gerados, eles estão alinhados com os requisitos.
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.