摇号中签生成随机号

article/2025/8/31 3:20:07

  在现在很多类似于股票市场的交易中,很多项目发行都需要进行申购,等到申购结束,进行摇号,根据中签尾号确定每个用户的中签数量。

如果用户U1购买了10个产品,那么他申购的产品尾号就是10000001到10000010,用户U2再购买5个,那么U2的产品尾号10000011到10000015。

现在假如发行项目A,发行量为12345,申购量为675893。随机生成中签尾号:

package com.fbd.core.util;import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;import com.fbd.core.exception.ApplicationException;/*** 摇号中签工具类 生成中签号码* * @author Lip**/
public class LotterySystem {// 已经选中的尾号的数量// public static long chooseNum = 0;public static void main(String[] args) {// 起始申购序列号long start = 10000000001L;// 实际申购数量long purchaseNum =675893;// 实际发行long distributeNum = 12345;Map<String, Integer> distributeMap = getLottery(purchaseNum, distributeNum);int total = 0;Iterator iterator = distributeMap.entrySet().iterator();while (iterator.hasNext()) {Entry entry = (Entry) iterator.next();System.out.println(entry.getKey() + ":" + entry.getValue());total += (int) entry.getValue();}System.out.println("中签数量:" + total);}/*** 得到各个尾数的中签数量* * @param purchaseNum* @param distributeNum* @return*/public static Map<String, Integer> getLottery(long purchaseNum, long distributeNum) {// 中签尾数及数量Map<String, Integer> distributeMap = new LinkedHashMap<>();if (purchaseNum <= distributeNum) {int n1 = (int) (purchaseNum % 10);int n2 = (int) (purchaseNum / 10);for (int i = 0; i < 10; i++) {if (i >= n1)distributeMap.put(i + "", n2);elsedistributeMap.put(i + "", n2 + 1);}return distributeMap;}long chooseNum = 0;double allocationRate = distributeNum * 1.0 / purchaseNum;// 0.001204177...System.out.println("中签率:" + allocationRate);int len = getDigitNum(purchaseNum);long distributeX = (long) (allocationRate * Math.pow(10, len));// 1204177List<Integer> digitList = getEachDigit(distributeX, len);// 1,2,0,4,1,7,7int lenX = getDigitNum(distributeX);List<Long> distributeList = new ArrayList<>();for (int i = 0; i < digitList.size(); i++) {int rate = digitList.get(i);// 尾号余数如232,158 也可以中奖long temp = (long) (purchaseNum % Math.pow(10, len - lenX + 1 + i));for (int j = 0; j < rate; j++) {if (chooseNum == distributeNum)return distributeMap;// 该随机号有多少个String lotteryNum = getRandom(distributeList, len - lenX + 1 + i);int number = (int) (purchaseNum * Math.pow(10, -(len - lenX + 1 + i)));long lotteryLong = Long.parseLong(lotteryNum);if (lotteryLong <= temp && lotteryLong > 0) {number++;}if (chooseNum + number <= distributeNum)chooseNum += number;elsebreak;distributeList.add(lotteryLong);distributeMap.put(lotteryNum, number);}}int left = (int) (distributeNum - chooseNum);while (left > 0)// 每次产生一个号码{String lotteryNum = getRandom(distributeList, len);long lotteryLong = Long.parseLong(lotteryNum);if (lotteryLong > purchaseNum || lotteryLong == 0) {continue;}distributeList.add(lotteryLong);distributeMap.put(lotteryNum, 1);left--;}return distributeMap;}/*** 得到一个数的位数* * @param value* @return*/public static int getDigitNum(long value) {return String.valueOf(value).length();}/*** 得到一个num位的随机数* * @param except* @param num* @return*/public static String getRandom(List<Long> except, int num) {boolean confict = true;long obj = 0l;while (confict) {obj = (long) (Math.random() * Math.pow(10, num));while (except.contains(obj) || obj == 0) {// obj肯定不在except中obj = (long) (Math.random() * Math.pow(10, num));}confict = false;int len = getLen(obj);for (long temp : except) {int len2 = getLen(temp);if (len2 == len) {continue;}if (Math.abs(obj - temp) % Math.pow(10, len2) == 0) // 有冲突{confict = true;break;}}}return String.format("%0" + num + "d", obj);}/*** 得到一个整数的位数* * @param num* @return*/public static int getLen(long num) {int len = 0;while (num != 0) {num /= 10;len++;}return len;}/*** 得到每位的中签比率* * @param value* @param len* @return*/public static List<Integer> getEachDigit(long value, int len) {String valueS = String.valueOf(value);List<Integer> result = new ArrayList<>();for (int i = 0; i < valueS.length() - 1; i++) {result.add(Integer.parseInt(valueS.charAt(i) + ""));}return result;}}
生成的中签尾号完全是随机的,如下图:

一个特殊的情况需要注意,那就是申购总量很少,小于发行量,那么相当于每个尾号都是中签的,当然,在实际中,这种情况不可能存在,出现那么也意味着该项目失败了。不过本文解决了申购量小于等于发行量的特殊情况。

该项目的中签率很低,用户U1和U2都不会中签。

算法原理:

  1. 计算中签率R=12345/675893=0.018264...
  2. 拆分小数位,百分位是为1,说明两位数的中签尾号有1个,千分位为8,说明三位数的中签尾号有8个....依次类推,直到产生足够的中签尾号
摇号结束后,知道了所有的中签尾号,也知道每个用户的购买数,那么可以计算每个用户的中签数量。我是利用存储过程来计算用户的中签数量的:
BEGINDECLARE v_num varchar(11);DECLARE v_len int;DECLARE done INT;DECLARE v_result int;DECLARE v_start_result int;DECLARE v_end_result int;DECLARE v_num_pow int;DECLARE cur_success CURSOR FOR SELECT number from lottery_number where project_id=projectId;DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;set v_result = 0;set v_start_result=0;set v_end_result=0;OPEN cur_success;BEGIN_success: LOOPFETCH cur_success INTO v_num;IF done THENLEAVE BEGIN_success;ELSEset v_len = LENGTH(v_num);set v_num_pow=POWER(10,v_len);set v_start_result=v_start_result+FLOOR(startNum/v_num_pow);IF startNum % v_num_pow>v_num THEN set v_start_result=v_start_result + 1;END IF;set v_end_result=v_end_result+FLOOR(endNum/v_num_pow);IF endNum%v_num_pow>=v_num THEN set v_end_result=v_end_result+1;END IF;END IF;END LOOP BEGIN_success;CLOSE cur_success;SET v_result=v_end_result-v_start_result;RETURN v_result;
END
原理其实很简单,每个用户都有一个起始配号,一个结束配号,那么只需要计算0到起始配号之间的中签数量n1,再计算0到结束配号之间的中签数量n2,那么n2-n1+1就是用户的中签数量。


http://chatgpt.dhexx.cn/article/ZJWxGKmh.shtml

相关文章

用JavaScript+HTML实现双色球随机摇号效果

用JavaScriptHTML实现双色球随机摇号效果 首先要知道双色球的规则是什么 双色球投注区分为红球号码区和蓝球号码区 红球号码范围为01&#xff5e;33&#xff0c;蓝球号码范围为01&#xff5e;16 双色球每期从33个红球中开出6个号码&#xff0c;从16个蓝球中开出1个号码作为中奖…

Java用n种方法编写实现双色球随机摇号案例

方法清单 规则实现方式一实现方式二实现方式三实现方式四实现方法五 之前我用JavaScript编写过一个实现双色球随机摇号的案例&#xff0c; 点击此处查看&#xff0c;今天我再用Java语言来实现这一效果。 规则 那么首先我们要搞清楚规则是什么&#xff1a; 双色球投注区分为红…

抽奖摇号系统随机性算法介绍

参考视频教程: **高并发高性能 Go语言开发企业级抽奖项目 ** 摘要 本文分析GO语言包中的"crypto/rand"和"math/rand"&#xff0c;芯链HPB系统的区块链随机数&#xff0c;并给出了权衡效率和随机性&#xff0c;并给出了一款区块链摇号抽奖系统如何…

Windows 安装 JDK-11

目标 在 windows 上安装 JDK-11 安装 下载 JDK 安装包 地址下载https://download.csdn.net/download/m0_47406832/83449704 解压 安装 运行 jdk-11.0.11_windows-x64_bin.exe 程序&#xff0c; 许可安装请求 等待环境检测 开始安装 选择安装目录 接下来一路下一步&…

Win10安装JDK11(超详细)

目录 一、下载JDK二、安装JDK三、配置环境变量四、检查是否安装成功五、JDK中没有jre文件 一、下载JDK JDK11下载地址&#xff1a; Java SE Development Kit 11.0.19 下图是JDK11下载界面&#xff1a; 其中.exe后缀的是安装版本&#xff0c;需要手动设置安装路径进行安装&am…

JDK11安装-macos

JDK 概述 JDK 全称 Java Development ToolKit&#xff0c;是 Java 语言开发工具包。JDK 是整个 JAVA 的核心&#xff0c;包括了 Java 运行环 境&#xff08;Java Runtime Environment&#xff09;&#xff0c;一堆 Java 工具&#xff08;javac/java/jdb 等&#xff09;和 Java…

jdk9、jdk10、jdk11、jdk12、jdk13新特性

我们绝大部分人估计都还在用着jdk8&#xff0c;12其实是一个非LTS&#xff08;long time support&#xff09;版本&#xff0c;而11与8一样是LTS版&#xff0c;意味着下个通用的版本将从8直接到11&#xff0c;毕竟11包含了9和10的所有新特性&#xff0c;因此9和10估计就直接被废…

window11安装JDK1.8【jdk-8u121】

&#x1f469;‍&#x1f4bb;博客主页&#xff1a;大家好我是poizxc2014的博客主页 ✨欢迎关注&#x1f5b1;点赞&#x1f380;收藏⭐留言✒ &#x1f4d6;个人主页&#xff1a;poizxc2014的博客_CSDN博客-数据库,mysql,java领域博主 &#x1f4bb;首发时间&#xff1a;&#…

JDK11 新特性详解

1、增强局部变量类型推断 var Consumer<String> consumer t -> System.out.println(t.toUpperCase()); Consumer<String> consumer (var t) -> System.out.println(t.toUpperCase());错误的形式&#xff1a;必须要有类型&#xff0c;可以加上var Consumer…

JDK11安装教程(WIN10)

文章目录 前言一、Java是什么&#xff1f;二、搭建Java环境1.下载2.安装3.配置环境变量4.检验是否安装成功 总结 前言 从毕业到工作已经快一年了&#xff0c;这一年来&#xff0c;公司给我的发展方向是项目经理&#xff0c;但是第一&#xff0c;工作地点离家太远&#xff1b;第…

【JDK】win 10 / win 11:jdk 8 下载、安装、配置、验证

目录 一、下载 JDK &#xff08;1&#xff09;官网下载 JDK 最新版本 &#xff08;2&#xff09;官网下载 JDK 历史版本&#xff08;示例 Java 8&#xff09; 二、安装 JDK &#xff08;1&#xff09;新建安装目录 jdk 和 jre &#xff08;2&#xff09;启动安装程序 &a…

【JDK】win 10 / win 11:jdk 8 升级为 jdk 17

目录 一、前言 二、历史版本 Java 安装 三、最新版本 Java 安装 &#xff08;1&#xff09;历史版本作废 &#xff08;2&#xff09;最新版本沿用旧版 JDK 系统环境变量 &#xff08;3&#xff09;JDK 17 下载 &#xff08;4&#xff09;JDK 17 安装 &#xff08;5&am…

Windows下安装JDK11(详细版)

简介 在JDK1.8之后的下一个稳定版本就是JDK11&#xff0c;所以下面教大家安装JDK11 第一步:下载 官网下载地址[https://www.oracle.com/java/technologies/javase-jdk11-downloads.html] 拉至页面到底部&#xff0c;选择如下版本下载&#xff0c;然后它可能要Oracle帐号才能…

Windows下安装JDK11(详细)

文章目录 一、简介第一步&#xff1a;下载第二步&#xff1a;安装第三步&#xff1a;设置环境变量第四步&#xff1a;生成 jre 文件第五步&#xff1a;检查是否成功 一、简介 因为JDK1.8版本已经不维护且比较老&#xff0c;故选用下一个稳定的版本&#xff0c;即JDK11。 第一…

win10安装jdk11

win10安装jdk11 jdk11下载与安装下载手动安装免安装配置系统环境变量检测是否安装成功 切换jdk版本 jdk11下载与安装 下载 1.第一步&#xff0c;前往oracle官网下载jdk11 oracle官方下载地址 2.选择要下载的jdk x64 Installer&#xff1a;这个是需要手工安装的版本 x64 Com…

jdk11下载与安装教程(win10)超详细

一、下载安装步骤 1、官网下载还需要注册&#xff0c;可以点【我的网盘】目录下载&#xff0c;密码3360&#xff0c;目录也有其它低版本的&#xff0c;如果有需要大家根据需要自行选择。 2、下载后直接点击安装程序&#xff0c;点击【运行】。这里我使用的是64位的。 3、点击【…

JDK11下载安装、JRE生成、环境配置

一、 下载 JDK11官网下载&#xff1a; Java SE - Downloads | Oracle Technology Network | Oracle 选择自己合适的版本。 二、安装 三、生成JRE 1、安装目录 找到jdk的安装目录 2、jdk11安装目录里面我们可以看到是没有jre的&#xff0c;但是我们在之后可能是会需要用到…

JDK11下载与安装 win10 64位

Java11 为LTS(长期支持)版本。 1.下载JDK11 建议直接找安装包&#xff0c;不要去官网下载。 下面是 jdk11的下载地方 方法1&#xff1a;百度网盘链接&#xff1a;https://pan.baidu.com/s/11yQTrDv653hceNA-wfcFsg 提取码&#xff1a;qgfk 方法2&#xff1a;阿里云盘&#xff1…

2020年最新 java JDK 11 下载、安装与环境变量配置教程

java JDK11下载、安装与环境变量配置 一、下载步骤 首先明确自己的操作系统&#xff08;本次配置jdk操作系统&#xff1a;Windows 10 家庭中文版&#xff09; 下载地址&#xff1a;点击跳转 点击进入下载地址后我们可以看见目前&#xff08;2020/8/15&#xff09;最新版本是…

Win10安装jdk11及环境变量配置

Win10安装jdk11及环境变量配置 写在前面卸载旧版本jdk下载jdk11配置环境变量经验教训 写在前面 我第一次安装java是在17年初&#xff0c;距离现在已经一年半了。今天上oracle官网一看&#xff0c;jdk都已经更新到11.0.1了&#xff0c;然而我用的还是1.8.0_171版本的老古董&…