miduo_server/gamecommon/src/main/java/util/MathUtils.java

407 lines
11 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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));
}
}