package com.snowcattle.game.common.util;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
* 从LZR拷贝过来
*
*/
public class MathUtils {
// public static final float EPSILON = 0.00001f;//10-6对于double转float容易误差
// 宠物点数校验时。 modified by sxf 090121
public static final float EPSILON = 0.00004f;// 再把误差调得大一点,现在这样,在150级时百万次检查大概会出现8次超出误差值
public static Random random = new Random();
/**
* 返回>=low, <=hi的整数随机数,均匀分布
*
* @param low
* @param hi
* @return
*/
public static int random(int low, int hi) {
return (int) (low + (hi - low + 0.9) * Math.random());
}
/**
* 返回>=low, <hi的浮点随机数,均匀分布
*
* @param low
* @param hi
* @return
*/
public static float random(float low, float hi) {
return (float) (low + (hi - low) * Math.random());
}
/**
* 非均匀分布的数组,返回命中数组元素的索引 全未命中返回-1
*
* @param rateArray
* 数组中各元素的值为该元素被命中的权重
* @return 命中的数组元素的索引
*/
public static int random(Integer[] rateArray) {
int[] rateArrayInt = new int[rateArray.length];
for (int i = 0; i < rateArray.length; i++) {
rateArrayInt[i] = rateArray[i];
}
return MathUtils.random(rateArrayInt);
}
/**
* 非均匀分布的数组,返回命中数组元素的索引 全未命中返回-1
*
* @param rateArray
* 数组中各元素的值为该元素被命中的权重
* @return 命中的数组元素的索引
*/
public static int random(int[] rateArray) {
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 (rateArray[i] < 0) {
throw new IllegalArgumentException(
"The array's element must not be equal or greater than zero!");
}
rateSum += rateArray[i];
rateSumArray[i] = rateSum;
}
if (rateSum <= 0) {
// 所有概率都为零,必然没有选中的元素,返回无效索引:-1
return -1;
}
int randomInt = MathUtils.random(1, rateSum);
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;
}
/**
* 返回是否满足概率值。
*
* @param shakeNum
* float 概率值 0.0---1.0
* @return 比如某操作有20%的概率,shakeNum=0.2 如果返回true表明概率满足。
*/
public static boolean shake(float shakeNum) {
if (shakeNum >= 1) {
return true;
}
if (shakeNum <= 0) {
return false;
}
double a = Math.random();
return a < shakeNum;
}
/**
* 从一个枚举中随机一个值
*
* @param enumClass
* 枚举类型
* @return 随机出的一个枚举值
*/
public static <T extends Enum<T>> T random(Class<T> enumClass) {
T[] elements = enumClass.getEnumConstants();
return elements[random(0, elements.length - 1)];
}
/**
* 注意如有需要,请使用@see {@link AIUtils#luckyDraw(float[])}
*
* 抽奖 按照rateAry[i]要求的概率 返回 i; 计算物品必然掉落的情况 适用
*
* @param rateAry
* 概率数组 要求 数组元素 和为1
* @return
*/
@Deprecated
public static int luckyDraw(float[] rateAry) {
if (rateAry == null) {
return -1;// modified by sxf 090310
}
int[] balls = new int[100];
int pt = 0;
for (int i = 0; i < rateAry.length; i++) {
int mulRate = (int) (rateAry[i] * 100);
for (int j = 0; j < mulRate; j++) {
try {
balls[pt] = i;
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
return rateAry.length - 1;
}
pt++;
}
}
return balls[random(0, 99)];
}
public static int parseInt(Object input, int defaultValue) {
if (input == null)
return defaultValue;
try {
return Integer.parseInt(input.toString());
} catch (Exception e) {
}
return defaultValue;
}
public static int compareFloat(float f1, float f2) {
float delta = f1 - f2;
if (Math.abs(delta) > EPSILON) {
if (delta > 0) {
return 1; // f1> f2
} else if (delta < 0) {
return -1;// f1<f2
}
}
return 0;// f1==f2
}
public static int compareToByDay(Calendar dayone, Calendar daytwo) {
if (dayone.get(Calendar.YEAR) > daytwo.get(Calendar.YEAR)) {
return 1;
} else if (dayone.get(Calendar.YEAR) < daytwo.get(Calendar.YEAR)) {
return -1;
} else {
if (dayone.get(Calendar.MONTH) > daytwo.get(Calendar.MONTH)) {
return 1;
} else if (dayone.get(Calendar.MONTH) < daytwo.get(Calendar.MONTH)) {
return -1;
} else {
if (dayone.get(Calendar.DAY_OF_MONTH) > daytwo
.get(Calendar.DAY_OF_MONTH)) {
return 1;
} else if (dayone.get(Calendar.DAY_OF_MONTH) < daytwo
.get(Calendar.DAY_OF_MONTH)) {
return -1;
} else {
return 0;
}
}
}
}
/**
* 计算两个日期间相差的天数(按24小时算)
*
* @param enddate
* @param begindate
* @return
*/
public static int getIntervalDays(Date enddate, Date begindate) {
long millisecond = enddate.getTime() - begindate.getTime();
int day = (int) (millisecond / 24l / 60l / 60l / 1000l);
return day;
}
/**
* 计算两个日期间相差的天数(按24小时算)
*
* @param enddate
* @param begindate
* @return
*/
public static int getIntervalDays(long enddate, long begindate) {
long millisecond = enddate - begindate;
int day = (int) (millisecond / 24l / 60l / 60l / 1000l);
return day;
}
/**
* 计算两个日期间相差的分钟数
*
* @param enddate
* @param begindate
* @return
*/
public static int getIntervalMinutes(Date enddate, Date begindate) {
long millisecond = enddate.getTime() - begindate.getTime();
int minute = (int) (millisecond / 60l / 1000l);
return minute;
}
/**
* 计算两个日期间相差的分钟数
*
* @param enddate
* @param begindate
* @return
*/
public static int getIntervalMinutes(long enddate, long begindate) {
int minute = (int) ((Math.abs(enddate - begindate)) / 60l / 1000l);
return minute;
}
/**
* 限置为 >=min <max的值
*
* @param original
* @param min
* @param max
* @return
*/
public static int setBetween(int original, int min, int max) {
if (original >= max) {
original = max - 1;
}
if (original < min) {
original = min;
}
return original;
}
/**
* 限置为 >=min <max的值
*
* @param original
* @param min
* @param max
* @return
*/
public static long setBetween(long original, long min, long max) {
if (original >= max) {
original = max - 1;
}
if (original < min) {
original = min;
}
return original;
}
/**
* @param ary1
* @param ary2
* @return ary1 >= ary2 true else false
*/
public static boolean compareArrays(int[] ary1, int[] ary2) {
if (ary1 != null && ary2 != null) {
if (ary1.length == ary2.length) {
for (int i = 0; i < ary1.length; i++) {
if (ary1[i] < ary2[i]) {
return false;
}
}
}
}
return true;
}
public static int float2Int(float f) {
return (int) (f + 0.5f);
}
/**
* 获取两数相除的结果,精确到小数
*
* @param num
* @param deno
* @return
*/
public static float doDiv(int numerator, int denominator) {
if (denominator != 0) {
return numerator / (denominator + 0.0f);
}
return 0f;
}
public static float doDiv(float numerator, float denominator) {
if (denominator != 0) {
return numerator / (denominator);
}
return 0f;
}
/**
* 两个正整数相加
*
* @param n1
* 第一个参数
* @param n2
* 第二个参数
* @return 相加后的结果
* @exception IllegalArgumentException
* ,如果n1或者n2有一个负数,则会抛出此异常;如果n1与n2相加后的结果是负数,即溢出了,也会抛出此异常
*/
public static int addPlusNumber(final int n1, final int n2) {
if (n1 < 0 || n2 < 0) {
throw new IllegalArgumentException(
"Both n1 and n2 must be plus,but n1=" + n1 + " and n2 ="
+ n2);
}
final int _sum = n1 + n2;
if (_sum < 0) {
throw new IllegalArgumentException(
"Add n1 and n2 must be plus,but n1+n2=" + _sum);
}
return _sum;
}
/**
* 比较两个flaot是否相等,用{@link Float#equals()}实现
*
* @param floatA
* @param floatB
* @return
*/
public static boolean floatEquals(float floatA, float floatB) {
return ((Float) floatA).equals(floatB);
}
/**
* 给定一系列事件的发生频率,以这个频率估计概率,随机选择一个事件发生
*
* @param frequencies
* 发生事件的频率数组
* @param excludeIndexSet
* 忽略的事件索引集合,这些事件的频率将被忽略,随机结果也不会返回这些索引<br/>
* 如果没有忽略的事件,可传入null
* @return 发生的事件索引,即在frequencies中的索引;频率全部为0则返回-1,表示没有事件发生
*/
public static int randomSelectByFrequency(final int[] frequencies,
BitSet excludeIndexSet) {
if (frequencies == null) {
throw new IllegalArgumentException("frequencies is null");
}
if (frequencies.length == 0) {
return -1;
}
int fromIndex = 0;
int toIndex = frequencies.length;
int total = 0;
for (int i = fromIndex; i < toIndex; i++) {
if (excludeIndexSet != null && excludeIndexSet.get(i)) {
continue;
}
if (frequencies[i] < 0) {
// 非法频率数据
throw new IllegalArgumentException(
"frequency must not be negative. freqencies:"
+ Arrays.toString(frequencies));
}
total += frequencies[i];
}
if (total <= 0) {
// 没有发生的事件
return -1;
}
int randomNum = random(1, total), happenIndex = -1;
int partSum = 0;
for (int i = fromIndex; i < toIndex; i++) {
if (excludeIndexSet != null && excludeIndexSet.get(i)) {
continue;
}
partSum += frequencies[i];
if (randomNum <= partSum) {
happenIndex = i;
break;
}
}
return happenIndex;
}
/**
* 对一组数求平均,结果趋向于较大的数
* <p>算法:例如有一组数为{ a, b, c },那么平均数 n = (a^4 + b^4 + c^4) / (a^3 + b^3 + c^3)
* <p><strong>要求给定的数全部大于0<br/>
* 计算过程使用int,三次方或者四次方后有可能会超出上限,所以不要传进太大的数</strong>
*
* @param nums 一组数
* @return 平均数
*/
public static int getAverageTendToGreater(int[] nums) {
if (nums == null || nums.length == 0) {
throw new IllegalArgumentException("no value");
}
if (nums.length == 1) {
return nums[0];
}
int total4 = 0, total3 = 0;
for (int i = 0; i < nums.length; i++) {
int num = nums[i], tmp = 0;
if (num <= 0) {
throw new IllegalArgumentException("num error");
}
tmp = num * num * num;
total3 += tmp;
tmp *= num;
total4 += tmp;
}
return (int)Math.round((double)total4 / total3);
}
/**
* 从一个数组中随机一个元素
*
* @param <T>
* @param array 一个数组
* @return 数组中的某个元素
*/
public static <T> T randomFromArray(T[] array) {
int len = array.length;
return array[random(0, len - 1)];
}
/**
* 随机一个数
*
* @param num
* @return
*/
public static int randomNextInt(int num) {
return random.nextInt(num);
}
/**
* 获取md5
* @param list
* @return
*/
public static byte[] getMd5(List<Integer> list){
byte[] result = new byte[list.size()];
for(int i = 0; i < list.size(); i++){
int key = list.get(i);
int keyByte = key & 0xFF;
result[i] = (byte) keyByte;
}
return result;
}
}