Java实现仿拼多多砍价算法

13079544-0511246bdcf3b400.png

最近的项目是与微信砍价有关,在微信里用户可以发起砍价,并邀请好友帮忙砍价,每个商品会有一个底价,并且固定砍价次数将商品从原价砍至底价,这样看来就很像微信分红包的规则了,假设200元的红包,10个人分,每个人金额随机,10个人分完200元。砍价也是一样,假设原价499,底价是299,那么邀请10个好友帮忙砍掉200元,10个好友每次砍的金额随机,第10个好友刚好砍至底价299。

实现思路:

1.用户发起砍价的时候就为用户分配好砍价的金额,将分配的金额以数组形式存入数据库
2.好友帮忙砍价的时候直接按照顺序去数据库取当前被分配的砍价金额

算法如下:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 *
 * @author cc
 * @Decription 砍价
 */
public class ReducePriceUtils {
    /**
     * 1.总金额不超过总共可砍的价格*100  单位是分
     * 2.每次砍价都能砍到金额,最低不能低于1分,最大金额不能超过(总共可砍的价)*100
     */
    private static final int MINMONEY = 1;
    private static final int MAXMONEY = 200*100;

    /**
     * 这里为了避免某一次砍价占用大量资金,我们需要设定非最后一次砍价的最大金额,
     * 我们把他设置为砍价金额平均值的N倍
     */
    private static final double TIMES = 3.1;

    /**
     * 砍价合法性校验
     * @param money
     * @param count
     * @return
     */
    private static boolean isRight(int money,int count){
        double avg = money/count;
        //小于最小金额
        if (avg<MINMONEY) {
            return false;
        }else if (avg>MAXMONEY) {
            return false;
        }
        return true;
    }

    /**
     * 随机分配一个金额
     * @param mnoney
     * @param minS:最小金额
     * @param maxS:最大金额
     * @param count
     * @return
     */
    private static int randomReducePrice(int money,int minS,int maxS,int count){
        //若只有一个,直接返回
        if (count==1) {
            return money;
        }
        //如果最大金额和最小金额相等,直接返回金额
        if (minS==maxS) {
            return minS;
        }
        int max=maxS>money?money:maxS;
        //分配砍价正确情况,允许砍价的最大值
        int maxY = money-(count-1)*minS;
        //分配砍价正确情况,允许砍价最小值
        int minY = money-(count-1)*maxS;
        //随机产生砍价的最小值
        int min = minS>minY?minS:minY;
        //随机产生砍价的最大值
        max = max>maxY?maxY:max;
        //随机产生一个砍价
        return (int)Math.rint(Math.random()*(max-min) +min);
    }

    /**
     * 砍价
     * @param money 可砍总价
     * @param count 个数
     * @return
     */
    public static List<Double> splitReducePrice(int money,int count){
        //红包合法性分析
        if (!isRight(money, count)) {
            return new ArrayList<>();
        }
        //红包列表
        List<Double> list = new ArrayList<>();
        //每个红包的最大的金额为平均金额的TIMES倍
        int max = (int)(money*TIMES/count);
        max = max>MAXMONEY?MAXMONEY:max;
        //分配红包
        int sum = 0;

        for(int i=0;i<count;i++){
            int one = randomReducePrice(money, MINMONEY, max, count-i);
            list.add(one/100.0);
            money-=one;
            sum += one;
        }
        System.out.println("sum:"+sum);
        return list;
    }

    public static void main(String[] args) {
        List<Double> list = splitReducePrice(19799, 10);
        System.out.println(list);
    }

砍价分配结果:

sum:19799
[1.65, 3.94, 4.29, 3.44, 1.09, 33.65, 11.41, 43.78, 46.74, 48.0]

这里为了方便小数的计算在最开始将金额扩大了100倍,然后最后计算出砍价的金额时再将金额除以100。

原文作者技术博客:https://www.jianshu.com/u/ac4daaeecdfe
95后前端妹子一枚,爱阅读,爱交友,将工作中遇到的问题记录在这里,希望给每一个看到的你能带来一点帮助。
欢迎留言交流

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值