At present, in many similar transactions in the stock market, many project issuance needs to be subscribed for, until the end of the subscription, the number of subscribers is determined by the subscription number.
If user U1 purchases 10 products, then the end number of the product he purchases is 10000001 to 100000010, and user U2 purchases five more, then U2's end number is 100000011 to 10000015.
Now if we issue item A, the circulation is 12345 and the subscription is 675893. Signature number in random generation:
-
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;
-
-
-
-
-
-
-
-
public class LotterySystem {
-
-
-
-
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("Number of successful signatures:" + total);
-
}
-
-
-
-
-
-
-
-
-
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);
-
else
-
distributeMap.put(i + "", n2 + 1);
-
}
-
return distributeMap;
-
}
-
long chooseNum = 0;
-
double allocationRate = distributeNum * 1.0 / purchaseNum;
-
System.out.println("Lottery rate:" + allocationRate);
-
int len = getDigitNum(purchaseNum);
-
long distributeX = (long) (allocationRate * Math.pow(10, len));
-
List<Integer> digitList = getEachDigit(distributeX, len);
-
int lenX = getDigitNum(distributeX);
-
List<Long> distributeList = new ArrayList<>();
-
for (int i = 0; i < digitList.size(); i++) {
-
int rate = digitList.get(i);
-
-
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;
-
else
-
break;
-
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;
-
}
-
-
-
-
-
-
-
-
public static int getDigitNum(long value) {
-
return String.valueOf(value).length();
-
}
-
-
-
-
-
-
-
-
-
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 = (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);
-
}
-
-
-
-
-
-
-
-
public static int getLen(long num) {
-
int len = 0;
-
while (num != 0) {
-
num /= 10;
-
len++;
-
}
-
return len;
-
}
-
-
-
-
-
-
-
-
-
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;
-
}
-
-
}
The generated signature number is completely random, as follows:

There is a special case need to be noted, that is, the total amount of purchase is very small, less than the circulation, then the equivalent of each tail number is signed, of course, in practice, this situation can not exist, then it means that the project failed. However, this paper solves the special case that the subscription volume is less than or equal to the issuance volume.
The success rate of this project is very low, users U1 and U2 will not be successful.
algorithm Principle:
- In the calculation, the signature rate R=12345/675893=0.018264.
- Divide decimal digits into decimal digits, the percentile is 1, which means that there is one middle signature number in two digits and 8 in thousand digits, which means that there are eight middle signature numbers in three digits.... Analogy in turn until enough middle signature numbers are generated.
At the end of the shake, you know all the winning numbers and the number of purchases per user, so you can calculate the number of winning signs per user. I use stored procedures to calculate the number of user winners:
-
BEGIN
-
DECLARE 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: LOOP
-
FETCH cur_success INTO v_num;
-
IF done THEN
-
LEAVE BEGIN_success;
-
ELSE
-
set 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
The principle is very simple. Every user has a start number and an end number. Then only need to calculate the number of winners between 0 and the start number n1, and then calculate the number of winners between 0 and the end number n2. Then n2-n1+1 is the number of winners.