407 lines
11 KiB
Java
407 lines
11 KiB
Java
package util;
|
||
|
||
import org.slf4j.Logger;
|
||
import org.slf4j.LoggerFactory;
|
||
|
||
import java.math.BigDecimal;
|
||
import java.util.*;
|
||
import java.util.concurrent.ThreadLocalRandom;
|
||
|
||
|
||
/**
|
||
* Created by admin on 2014/11/14.
|
||
* 随机工具类
|
||
*/
|
||
|
||
public class MathUtils {
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(MathUtils.class);
|
||
|
||
private static final Random random = new Random();
|
||
|
||
|
||
public static void main(String[] args){
|
||
for(int j = 0 ; j <100;j++){
|
||
int i = randomInt(3);
|
||
System.out.println(i);
|
||
}
|
||
}
|
||
public static int randomForStrArray(String [] rateArray) {
|
||
return randomStrArray(rateArray, -1);
|
||
}
|
||
public static int randomStrArray(String [] rateArray, int minSum) {
|
||
if (null == rateArray) {
|
||
throw new IllegalArgumentException(
|
||
"The random array must not be null!");
|
||
}
|
||
int arrayLength = rateArray.length;
|
||
if (arrayLength == 0) {
|
||
throw new IllegalArgumentException(
|
||
"The random array's length must not be zero!");
|
||
}
|
||
// 依次累加的和
|
||
int rateSum = 0;
|
||
// 从头开始 依次累加之后的各个元素和 的临时数组
|
||
int[] rateSumArray = new int[arrayLength];
|
||
|
||
for (int i = 0; i < arrayLength; i++) {
|
||
|
||
if (Integer.parseInt(rateArray[i]) < 0) {
|
||
throw new IllegalArgumentException(
|
||
"The array's element must not be equal or greater than zero!");
|
||
}
|
||
rateSum += Integer.parseInt(rateArray[i]);
|
||
rateSumArray[i] = rateSum;
|
||
}
|
||
if (rateSum <= 0) {
|
||
// 所有概率都为零,必然没有选中的元素,返回无效索引:-1
|
||
return -1;
|
||
}
|
||
//如果有保底分母设置,当所有权值之和小于保底分母时,则启用保底分母
|
||
if(minSum < rateSum) {
|
||
minSum = rateSum;
|
||
}
|
||
int randomInt = MathUtils.random(1, minSum);
|
||
if(randomInt > rateSum) {
|
||
return -1;
|
||
}
|
||
int bingoIndex = -1;
|
||
for (int i = 0; i < arrayLength; i++) {
|
||
if (randomInt <= rateSumArray[i]) {
|
||
bingoIndex = i;
|
||
break;
|
||
}
|
||
}
|
||
if (bingoIndex == -1) {
|
||
throw new IllegalStateException("Cannot find out bingo index!");
|
||
}
|
||
return bingoIndex;
|
||
}
|
||
/**
|
||
* 返回>=low, <=hi的整数随机数,均匀分布
|
||
*
|
||
* @param low
|
||
* @param hi
|
||
* @return
|
||
*/
|
||
public static int random(int low, int hi) {
|
||
// return (int) (low + (hi - low + 0.9) * Math.random());
|
||
return low + ThreadLocalRandom.current().nextInt(hi - low + 1);
|
||
}
|
||
|
||
/**
|
||
* 返回 0~n-1 的整数
|
||
* @param n
|
||
* @return
|
||
*/
|
||
public static int randomInt(int n){
|
||
return random.nextInt(n);
|
||
}
|
||
|
||
public static int randomInt(){
|
||
return random.nextInt();
|
||
}
|
||
|
||
public static int numRount(float num){
|
||
return Math.round(num);
|
||
}
|
||
|
||
public static long numRount(double num){
|
||
return Math.round(num);
|
||
}
|
||
/**
|
||
* 限置为 >=min <= max的值
|
||
*
|
||
* @param original
|
||
* @param min
|
||
* @param max
|
||
* @return
|
||
*/
|
||
public static int setBetweenWithMax(int original, int min, int max) {
|
||
if (original >= max) {
|
||
original = max;
|
||
}
|
||
if (original < min) {
|
||
original = min;
|
||
}
|
||
return original;
|
||
}
|
||
|
||
public static int getMaxNum(int a, int b) {
|
||
if(a>=b){
|
||
return a;
|
||
}
|
||
return b;
|
||
}
|
||
|
||
//ab x 公式
|
||
public static float calABX(float source,float[] base){
|
||
float result = 0;
|
||
int length = base.length;
|
||
for(int i=0;i< base.length;i++){
|
||
double pow = Math.pow(source, --length);
|
||
result += base[i]*pow;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
//ab x 公式
|
||
public static float calABX(float source,int[] base){
|
||
float result = 0;
|
||
int length = base.length;
|
||
for(int i=0;i< base.length;i++){
|
||
double pow = Math.pow(source, --length);
|
||
result += base[i]*pow;
|
||
}
|
||
return result;
|
||
}
|
||
public static int randomFromWeightReturnIndex(int[][] array){
|
||
int amount = 0;
|
||
int result = 0;
|
||
for(int i = 0 ; i <array.length;i++){
|
||
amount+=array[i][1];
|
||
|
||
}
|
||
int rate = MathUtils.randomInt(amount);
|
||
amount = 0;
|
||
for (int i = 0 ; i<array.length;i++){
|
||
amount+=array[i][1];
|
||
if(rate<amount){
|
||
result = i;
|
||
break;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
public static int randomFromArray(int[] array){
|
||
if(array.length>0){
|
||
return array[(int) Math.floor(Math.random()*array.length)];
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* 根据数组索引就行随机
|
||
* @param sourceArray
|
||
* @param randomNums
|
||
* @return
|
||
*/
|
||
public static List<Integer> randomForOneArray(int sourceArray[], int randomNums) {
|
||
|
||
List<Integer> result = new ArrayList<>();
|
||
if(randomNums==0){
|
||
return result;
|
||
}
|
||
int length = sourceArray.length;
|
||
Set<Integer> cacheIndexs = new HashSet<>();
|
||
|
||
// 这种while循环我觉得还是尽量避免下 或者一定要有个循环上限
|
||
while (randomNums>0){
|
||
int randomPos = randomInt(length);
|
||
if(cacheIndexs.contains(randomPos)){
|
||
continue;
|
||
}
|
||
cacheIndexs.add(randomPos);
|
||
result.add(sourceArray[randomPos]);
|
||
randomNums--;
|
||
}
|
||
return result;
|
||
|
||
}
|
||
|
||
public static int getTheIndexByTarget(int[][] sourceArray,int target){
|
||
for(int i=0;i<sourceArray.length;i++){
|
||
int[] item = sourceArray[i];
|
||
if(target>=item[0] && target<=item[1]){
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
public static int randomFromWeight(int[][] array){
|
||
int index = randomFromWeightReturnIndex(array);
|
||
return array[index][0];
|
||
}
|
||
|
||
public static int[] randomFromWeight(int[][][] arrays){
|
||
int[] result = new int[arrays.length];
|
||
int i=0;
|
||
for(int[][] array : arrays){
|
||
int index = randomFromWeightReturnIndex(array);
|
||
result[i++] = array[index][0];
|
||
}
|
||
return result;
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* 根据权重,不放回随机
|
||
* @param array
|
||
* @param count 随机个数
|
||
* @return
|
||
*/
|
||
public static int[] randomFromWeightWithTaking(int[][] array,int count){
|
||
|
||
if(array.length<count){
|
||
throw new IllegalArgumentException(array.length+"<"+count);
|
||
}
|
||
if(count==1){
|
||
return new int[]{randomFromWeight(array)};
|
||
}
|
||
int[] result = new int[count];
|
||
int[][] tempArray = new int[array.length][];
|
||
for(int i = 0 ; i <array.length;i++){
|
||
tempArray[i] = array[i];
|
||
}
|
||
for(int i = 0; i < count; i++){
|
||
int index = randomFromWeightReturnIndex(tempArray);
|
||
result[i] = tempArray[index][0];
|
||
tempArray[index] = tempArray[tempArray.length-1];
|
||
tempArray = Arrays.copyOf(tempArray,tempArray.length-1);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 根据层数重置
|
||
* @param tower
|
||
* @return
|
||
*/
|
||
public static int resetMethod(int tower){
|
||
int afterResetTower = tower-(tower%5);
|
||
// LOGGER.info("重置当前层,当前层为{},重置为{}",mapManager.getTower(),afterResetTower);
|
||
if(tower==0){
|
||
return 1;
|
||
} else if(tower>=5){
|
||
return afterResetTower;
|
||
}else{
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
|
||
public static int randomWeight(int[][] source,Set<Integer> excluIndexs){
|
||
int length = source.length;
|
||
int randomIndex = 0;
|
||
int times=100;
|
||
while (times-->0){
|
||
randomIndex= randomInt(length);
|
||
if(!excluIndexs.contains(randomIndex)){
|
||
break;
|
||
}
|
||
}
|
||
if(times<=0){
|
||
return -1;
|
||
}
|
||
excluIndexs.add(randomIndex);
|
||
return randomIndex;
|
||
}
|
||
|
||
//计算最大公约数
|
||
public static int getGCD(int a,int b){
|
||
if(a<0 || b<0){
|
||
return -1;
|
||
}
|
||
if(b==0){
|
||
return a;
|
||
}
|
||
while (a%b!=0){
|
||
int temp = a % b;
|
||
a = b;
|
||
b = temp;
|
||
}
|
||
return b;
|
||
}
|
||
|
||
|
||
public static List<Integer> combineList(int start,int end){
|
||
List<Integer> list = new ArrayList<>();
|
||
while (start<=end){
|
||
list.add(start);
|
||
start++;
|
||
}
|
||
// Collections.shuffle(list);
|
||
return list;
|
||
}
|
||
|
||
/**
|
||
* 将数组均匀拆分为几份
|
||
*/
|
||
public static List<Integer> average(int sum, int split) {
|
||
List<Integer> result = new ArrayList<>();
|
||
if (split == 0) {
|
||
LOGGER.error("randomForOneArray::IllegalArgumentException");
|
||
return result;
|
||
}
|
||
int remain = sum % split;
|
||
int out = split - remain;
|
||
int item = (sum+out) / split;
|
||
for (int i = 0; i < split; i++) {
|
||
int innerItem = i == 0 ? item-out : item;
|
||
result.add(innerItem);
|
||
}
|
||
return result;
|
||
}
|
||
public static double forceToDouble(double force){
|
||
return force/Math.pow(10,8);
|
||
}
|
||
|
||
/**
|
||
* 根据权重纯随机
|
||
* @return
|
||
*/
|
||
public static int[] randomForWeight(int[][] array,int count){
|
||
int sum = 0;
|
||
for(int[] weight:array){
|
||
sum+=weight[1];
|
||
}
|
||
int[] random = new int[sum];
|
||
int index = 0 ;
|
||
for(int[] oneArray:array){
|
||
for(int i = 0;i< oneArray[1];i++){
|
||
random[index] = oneArray[0];
|
||
index++;
|
||
}
|
||
}
|
||
int[] result = new int[count];
|
||
for(int i = 0 ; i <result.length;i++){
|
||
result[i] =random[randomInt(random.length)];
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
*
|
||
* to fix zsx
|
||
* <li>
|
||
* When a {@code double} must be used as a source for a
|
||
* {@code BigDecimal}, note that this constructor provides an
|
||
* exact conversion; it does not give the same result as
|
||
* converting the {@code double} to a {@code String} using the
|
||
* {@link Double#toString(double)} method and then using the
|
||
* {@link #BigDecimal(String)} constructor. To get that result,
|
||
* use the {@code static} {@link #valueOf(double)} method.
|
||
* </ol>
|
||
* @param d1
|
||
* @param d2
|
||
* @return
|
||
*/
|
||
public static double doubleAdd(double d1 ,double d2){
|
||
BigDecimal b1 = new BigDecimal(String.valueOf(d1));
|
||
BigDecimal b2 = new BigDecimal(String.valueOf(d2));
|
||
return b1.add(b2).doubleValue();
|
||
}
|
||
|
||
public static double doubleSubtract(double d1 ,double d2){
|
||
BigDecimal b1 = new BigDecimal(String.valueOf(d1));
|
||
BigDecimal b2 = new BigDecimal(String.valueOf(d2));
|
||
return b1.subtract(b2).doubleValue();
|
||
}
|
||
|
||
public static double floatToDouble(float f){
|
||
return Double.parseDouble(Float.toString(f));
|
||
}
|
||
|
||
}
|