目录
题目描述
请实现微信拼手气红包算法,输入红包总额,输出红包抽取后的数值序列,算法考虑公平性、随机性。题目答案要求:总和为金额数,个数为红包数,单个金额不小于0.01,取两位小数。
解决方案
如果0.01 * 红包个数大于总金额,这种情况下钱不够分。
对每一个抢到的红包预先分配0.01元,分配后剩下的金额为:总金额 - 0.01 * 红包个数。利用循环将每一个红包随机的从剩下的金额池中选取一个随机数,将该随机数作为抢到的金额与预分配0.01相加即为最终的结果。
为了完全保证公平性,在返回最终序列之前,需要将序列打乱(因为在上述的随机从金额池抽取的过程中,会出现前几个红包将金额池瓜分完,导致后面的红包全部是0.01,因此不能保证完全的公平)。
代码
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print("请输入总金额:")
amountBytes, _, _ := reader.ReadLine()
amount, err := strconv.ParseFloat(string(amountBytes), 10)
if err != nil {
fmt.Println("请输入合法的总金额格式。")
return
}
fmt.Print("请输入红包个数:")
numberBytes, _, _ := reader.ReadLine()
number, err := strconv.Atoi(string(numberBytes))
if err != nil {
fmt.Println("请输入整数。")
return
}
pool := amount - float64(number)*0.01
if pool < 0 {
fmt.Println("红包不够分")
return
}
pool = pool * 100
result := make([]float64, 0)
for i := 0; i < number; i++ {
if i == number-1 {
packet := Decimal(pool*0.01 + 0.01)
result = append(result, packet)
continue
}
packet := rand.Intn(int(pool))
pool = pool - float64(packet)
result = append(result, Decimal(float64(packet)*0.01+0.01))
}
Suffix(&result)
fmt.Println(result)
}
func Decimal(value float64) float64 {
value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
return value
}
func Suffix(list *[]float64) {
length := len(*list)
if length <= 1 {
return
}
for i := 0; i < length; i++ {
randIndex := rand.Intn(length)
(*list)[i], (*list)[randIndex] = (*list)[randIndex], (*list)[i]
}
}
代码走读
package main import ( "bufio" "fmt" "math/rand" "os" "strconv" ) func main() { // 从控制台读取总金额、红包个数 reader := bufio.NewReader(os.Stdin) fmt.Print("请输入总金额:") amountBytes, _, _ := reader.ReadLine() amount, err := strconv.ParseFloat(string(amountBytes), 10) if err != nil { fmt.Println("请输入合法的总金额格式。") return } fmt.Print("请输入红包个数:") numberBytes, _, _ := reader.ReadLine() number, err := strconv.Atoi(string(numberBytes)) if err != nil { fmt.Println("请输入整数。") return } // 为每一个红包预分配0.01元,然后将剩余的金额放入红包池中 pool := amount - float64(number)*0.01 if pool < 0 { fmt.Println("红包不够分") return } // 将红包池转换成以分为单位的数字 pool = pool * 100 // 为每一个红包分配随机的金额,随机数分布在 0 ~ pool result := make([]float64, 0) for i := 0; i < number; i++ { // 如果是最后一个红包,则将pool内的剩余金额全部分配 if i == number-1 { packet := Decimal(pool*0.01 + 0.01) result = append(result, packet) continue } packet := rand.Intn(int(pool)) pool = pool - float64(packet) result = append(result, Decimal(float64(packet)*0.01+0.01)) } // 打乱分配结果 Suffix(&result) fmt.Println(result) } // 将一个浮点数保留两位小数 func Decimal(value float64) float64 { value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64) return value } // 打乱序列 func Suffix(list *[]float64) { length := len(*list) if length <= 1 { return } for i := 0; i < length; i++ { randIndex := rand.Intn(length) (*list)[i], (*list)[randIndex] = (*list)[randIndex], (*list)[i] } }