网上流传的红包 Money 分配算法


发布于

|

分类

代码不长,直接看 getMoneyRandomly 就好:

# -*- coding: UTF-8 -*-
__author__ = 'haoyu'

import math
import random


class RedPack:
    peopleTotal = 0
    peopleLeft = 0.0
    moneyTotal = 0
    moneyLeft = 0.0

    isInitlized = False
    isFinish = True

    def __init__(self, people, money):
        # 金额取两位小数
        money = round(money, 2)

        if money <= 0.01:
            print('错误:金额不能少于0.01元')
            return
        if people < 1:
            print('错误:至少1人')
            return
        if (math.floor(money * 100 / people)) / 100 < 0.01:
            print('错误:每人至少0.01元')
            return

        # 初始化
        self.peopleTotal = people
        self.peopleLeft = people
        self.moneyTotal = money
        self.moneyLeft = money
        self.isInitlized = True
        self.isFinish = False

        print('总金额: %.2f 元,总人数: %2d 人' % (self.moneyLeft, self.peopleTotal))
        print()

    def getMoneyRandomly(self):
        money = 0
        # 验证
        if not self.isInitlized:
            print('错误:没有初始化')
            return money
        if self.isFinish:
            print('错误:已经分配完毕')
            return money

        # 分配Money
        if self.peopleLeft == 1:
            self.isFinish = True
            money = self.moneyLeft
        else:
            minMoney = 0.01
            maxMoney = self.moneyLeft / self.peopleLeft * 2
            money = random.random() * maxMoney
            money = max(money, minMoney)
            money = min(money, self.moneyLeft - (self.peopleLeft - 1) * minMoney)

        # 分配过后的一些收尾工作
        self.peopleLeft -= 1
        money = round(money, 2)
        self.moneyLeft -= money

        return money


moneyPack = RedPack(10, 10)  # 10个人,总共分10元钱
totalMoney = 0
for i in range(moneyPack.peopleTotal):
    money = moneyPack.getMoneyRandomly()
    print('第%d人: %.2f 元,剩余 %.2f 元' % (i + 1, money, moneyPack.moneyLeft))
    totalMoney += money

print()
print('分配: %.2f 元,剩余: %.2f 元' % (totalMoney, moneyPack.moneyLeft))

原来的版本内部都是float实现的,但是好像处理小数精度会出一点问题,导致总是有几分钱分配不完。

然后内部就改成了int来玩了(两位定点小数嘛,还算好处理),稍微好了一点吧。

然后,觉得这样有些不妥,里面要脑补一个100的转换。于是还改为float,但是使用round()函数。这下更好一点了。

不理解,为什么要“最多能得到平均值的2倍”,这个设定有什么意义?

还有,按照这个代码,10个人瓜分0.2元钱,第一个人最多拿到0.04元,但是在WX某次红包中,我发现第一个人拿到了0.05元。很是奇怪錒~

总之呢,一段比较有趣的代码。

玩开心就好~


评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注