主要用于分批次,在指定数值之间分拆分出合理数值,不过度偏移
@Slf4j
public class BaseTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
service = Executors.newSingleThreadExecutor();
service = Executors.newScheduledThreadPool(3);
service = Executors.newFixedThreadPool(5);
for (int j = 0; j < 10; j++) {
log.info("************************");
NewClass newClass = new NewClass();
int length = 12;
int minl = 3000 / 1000 + 1;
int[] newArray = BaseTest.randDivide(10, 1000, 3000, minl, newClass);
int[] largeRandSyncopate = filterZero(newArray);
int maxL = 7000 / newClass.getNMax().intValue();
log.info("最大长度 >> " + maxL);
log.info("长度 >> " + largeRandSyncopate.length + " >> " +
Arrays.toString(largeRandSyncopate) + ":" + newClass.getNMax().intValue());
int[] result = BaseTest.randDivide(10, newClass.getNMax().intValue(), 7000, length - minL, newClass);
if (result == null) {
log.info("請增加本金或天數");
}
int[] smallRandSyncopate = filterZero(result);
int[] smallRandSyncopate = filterZero(ss2);
System.out.println("长度 >>> " + smallRandSyncopate.length + " >> " + Arrays.toString(smallRandSyncopate));
// int [] allRandSyncopate = ArrayUtils.addAll(largeRandSyncopate, smallRandSyncopate);
//System.out.println("length:" + allRandSyncopate.length +" >> " + Arrays.toString(allRandSyncopate));
}
}
/**
* 过滤出为0的数字
* @param newArray
* @return
*/
public static int[] filterZero(int[] newArray) {
int j = 0;
for (int i = 0; i < newArray.length; i++) {
if (newArray[i] > 0) {
j++;
}
}
int[] array = new int[j];
for (int i = 0; i < newArray.length; i++) {
if (newArray[i] > 0) {
array[i] = newArray[i];
}
}
return array;
}
/**
* 冒泡排序
* @param arr
* @return
*/
public static int[] sort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] < arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
/**
* 随机分配
* @param min
* @param max
* @param summary
* @param length
* @param newClass
* @return
*/
public static int[] randDivide(int min, int max, int summary, int length, NewClass newClass) {
//int maxl = summary % min == 0 ? summary / min : summary / (min + 1);
int minL = summary % max == 0 ? summary / max : summary / max + 1;
if (length < minL) {
System.out.println("/?????");
return null;
}
int[] k = new int[length];
// l:用来记录数组k中存储值的最后索引
int l = 0;
int total = 0;
if (min == max) {// 如果两数相等,则常数
if (summary % min == 0) {
for (int i = 0; i < k.length; i++) {
k[i] = min;
}
}
} else {
log.info("*** 分配开始 **");
Random rand = new Random();
int remainder;
BigDecimal nMax = BigDecimal.ONE;
for (int i = 1; i < k.length + 1; i++) {
remainder = summary - total;
nMax = nMax.compareTo(BigDecimal.ONE) == 0 ? BigDecimal.valueOf(max) : nMax;
nMax = nMax.subtract(nMax.multiply(BigDecimal.valueOf(0.004)));
if (remainder >= min && remainder <= max && remainder < nMax.intValue()) {
if (i == length) {
randDivideRemainder(summary, max, k, l, remainder);
break;
}
k[i] = remainder;
break;
} else if (remainder < min) {
if (i < minL) {
// 如果i<最小数组长度,则缩减分配
k[i] = remainder;
l = i;
randDivideLessenFiller(summary, min, k, l);
} else {
// 如果i>=最小数组长度,做叠加分配
randDivideRemainder(summary, max, k, l, remainder);
}
break;
}
log.info(length + "--" + i);
if (i == length) {
randDivideRemainder(summary, max, k, l, remainder);
break;
} else {
int rd = rand.nextInt(nMax.intValue() - min + 1) + min;
log.info(i + "_rd:" + rd + "-- nMax:" + nMax + "--total:" + total);
k[i] = rd;
total += rd;
l = i;
}
}
newClass.setNMax(nMax);
log.info("*** 分配结束 **");
}
int t = 0;
for (int i = 0; i < k.length; i++) {
if (k[i] < min || k[i] > max) {
break;
}
t += k[i];
}
if (t != summary) {
System.out.println("null");
return null;
}
return k;
}
// 随机出数字在指定大小中随机
private static void randDivideLessenFiller(int summary, int min, int[] k, int l) {
if (summary / (l + 1) < min)
return;
Random rand = new Random();
// 最小值与平均数之间的一个随机数
int rv = rand.nextInt(summary / (l + 1) - min + 1) + min;
int r = rv - k[l];
int j = 0;
while (r > 0 && j < 1000) {
int i = rand.nextInt(l);
if (k[i] - r >= min) {
k[i] -= r;
k[l] += r;
break;
}
int _r = rand.nextInt(r) + 1;
if (k[i] - _r >= min) {
k[i] -= _r;
k[l] += _r;
r -= _r;
}
j++;
}
}
/**
* l:数组最后的长度 r:余数 d:控制随机分配深度,j值一般达不到1000,防止无解导致栈溢出
*/
private static void randDivideRemainder(int summary, int max, int[] k, int l, int r) {
if (summary / (l + 1) > max)
return;
Random rand = new Random();
int j = 0;
while (r > 0 && j < 1000) {
int i = rand.nextInt(l);
if (k[i] + r <= max) {
k[i] = k[i] + r;
break;
}
int _tempMax = rand.nextInt(max - summary / (l + 1) + 1) + summary / (l + 1);
for (int t = 0; t <= l; t++) {
if (k[t] < _tempMax) {
// 最大数为程序要求的区间最大数-k[i],即空间与余数作比较
int _max = (_tempMax - k[t]) < r ? (_tempMax - k[t]) : r;
if (_max == 0)
continue;
// 这里仍用随机数,而不是自动填补的原因是,不让数字整齐
int rn = rand.nextInt(_max) + 1;
k[t] += rn;
r -= rn;
}
}
j++;
}
}
}
@Data
@Slf4j
class Concurrence implements Runnable {
private String name;
public Concurrence(String name) {
// TODO Auto-generated constructor stub
this.name = name;
}
@Override
public synchronized void run() {
String s = new Thread().getName();
for (int j = 0; j < 10; j++) {
long start = System.currentTimeMillis();
NewClass newClass = new NewClass();
int[] ss = BaseTest.randDivide(505, 1000, 10000, 10, newClass);
long end = System.currentTimeMillis() - start;
int p = 0;
int max = 0;
for (int i = 0; i < ss.length; i++) {
p = p + ss[i];
if (ss[i] > 0) {
max++;
}
}
int maxL = 10000 % 505 == 0 ? (10000 / 505) : 10000 / (505 + 1);
// BaseTest.sort(ss);
log.info(s + ":nameL:" + name + "" + ">>--time:" + end + "--length:" + maxL + "-" + max
+ "--array:" + Arrays.toString(ss));
}
}
}
@Data
class NewClass{
private BigDecimal nMax = BigDecimal.ONE;
}