| package com.xzx.gc.util;  | 
|   | 
| import lombok.extern.slf4j.Slf4j;  | 
| import org.apache.commons.lang3.StringUtils;  | 
| import org.springframework.stereotype.Component;  | 
| import org.springframework.stereotype.Service;  | 
|   | 
| import java.math.BigDecimal;  | 
| import java.math.RoundingMode;  | 
| import java.text.DecimalFormat;  | 
| import java.util.Random;  | 
| import java.util.regex.Pattern;  | 
|   | 
| @Slf4j  | 
| public class DoubleUtil {  | 
|   | 
|     // 默认除法运算精度  | 
|     private static final Integer DEF_DIV_SCALE = 10;  | 
|     private static final String REGEX_MOBILE ="((\\+86|0086)?\\s*)((134[0-8]\\d{7})|(((13([0-3]|[5-9]))|(14[5-9])|15([0-3]|[5-9])|(16(2|[5-7]))|17([0-3]|[5-8])|18[0-9]|19(1|[8-9]))\\d{8})|(14(0|1|4)0\\d{7})|(1740([0-5]|[6-9]|[10-12])\\d{7}))";  | 
|     static Random random = new Random();  | 
|     static {  | 
|         random.setSeed(System.currentTimeMillis());  | 
|     }  | 
|     /**  | 
|      * 提供精确的加法运算。  | 
|      * @param value1 被加数  | 
|      * @param value2 加数  | 
|      * @return 两个参数的和  | 
|      */  | 
|     public static Double add(Double value1, Double value2) {  | 
|         BigDecimal b1 = new BigDecimal(Double.toString(value1));  | 
|         BigDecimal b2 = new BigDecimal(Double.toString(value2));  | 
|         return b1.add(b2).doubleValue();  | 
|     }  | 
|   | 
|     /**  | 
|      * 提供精确的减法运算。  | 
|      * @param value1 被减数  | 
|      * @param value2 减数  | 
|      * @return 两个参数的差  | 
|      */  | 
|     public static double sub(Double value1, Double value2) {  | 
|         BigDecimal b1 = new BigDecimal(Double.toString(value1));  | 
|         BigDecimal b2 = new BigDecimal(Double.toString(value2));  | 
|         return b1.subtract(b2).doubleValue();  | 
|     }  | 
|   | 
|     /**  | 
|      * 提供精确的乘法运算。  | 
|      * @param value1 被乘数  | 
|      * @param value2 乘数  | 
|      * @return 两个参数的积  | 
|      */  | 
|     public static Double mul(Double value1, Double value2) {  | 
|         BigDecimal b1 = new BigDecimal(Double.toString(value1));  | 
|         BigDecimal b2 = new BigDecimal(Double.toString(value2));  | 
|         return b1.multiply(b2).doubleValue();  | 
|     }  | 
|   | 
|     /**  | 
|      * 提供(相对)精确的除法运算,当发生除不尽的情况时, 精确到小数点以后10位,以后的数字四舍五入。  | 
|      * @param dividend 被除数  | 
|      * @param divisor 除数  | 
|      * @return 两个参数的商  | 
|      */  | 
|     public static Double divide(Double dividend, Double divisor) {  | 
|         if(divisor.intValue() == 0){ return 0.0;}  | 
|         return divide(dividend, divisor, DEF_DIV_SCALE);  | 
|     }  | 
|   | 
|     /**  | 
|      * 提供(相对)精确的除法运算。 当发生除不尽的情况时,由scale参数指定精度,以后的数字四舍五入。  | 
|      * @param dividend 被除数  | 
|      * @param divisor 除数  | 
|      * @param scale 表示表示需要精确到小数点以后几位。  | 
|      * @return 两个参数的商  | 
|      */  | 
|     public static Double divide(Double dividend, Double divisor, Integer scale) {  | 
|         if (scale < 0) {  | 
|             throw new IllegalArgumentException("The scale must be a positive integer or zero");  | 
|         }  | 
|         BigDecimal b1 = new BigDecimal(Double.toString(dividend));  | 
|         BigDecimal b2 = new BigDecimal(Double.toString(divisor));  | 
|         return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();  | 
|     }  | 
|   | 
|   | 
|     public static String roundThree(String value){  | 
|         DecimalFormat format = new DecimalFormat("0.000");  | 
|         return format.format(new BigDecimal(value));  | 
|     }  | 
|     public static String roundTwo(String value){  | 
|         DecimalFormat format = new DecimalFormat("0.00");  | 
|         return format.format(new BigDecimal(value));  | 
|     }  | 
|     public static String roundSix(String value){  | 
|         DecimalFormat format = new DecimalFormat("0.000000");  | 
|         return format.format(new BigDecimal(value));  | 
|     }  | 
|     public static String roundFive(String value){  | 
|         DecimalFormat format = new DecimalFormat("0.00000");  | 
|         return format.format(new BigDecimal(value));  | 
|     }  | 
|     public static String roundOne(String value){  | 
|         DecimalFormat format = new DecimalFormat("0.0");  | 
|         return format.format(new BigDecimal(value));  | 
|     }  | 
|   | 
|     public static Double roundByScale(double v, int scale) {  | 
|         if (scale < 0) {  | 
|             throw new IllegalArgumentException(  | 
|                     "保留位数不能小于0!");  | 
|         }  | 
|         if(scale == 0){  | 
|             return new Double("0");  | 
|         }  | 
|         String formatStr = "0.";  | 
|         for(int i=0;i<scale;i++){  | 
|             formatStr = formatStr + "0";  | 
|         }  | 
|         String str =  new DecimalFormat(formatStr).format(v);  | 
|   | 
|         DecimalFormat df = new DecimalFormat(formatStr);  | 
|         System.out.println(str);  | 
|         return  Double.parseDouble(str);  | 
|     }  | 
|   | 
|   | 
|   | 
|   | 
|   | 
|     public static double restRound(double min,double max,int i,double money,int count){  | 
|         double redpac=0;  | 
|         if(i==19){  | 
|             redpac=money;  | 
|         }else{  | 
|             redpac=(Math.random()*(max-min)+min)/100;  | 
|         }  | 
|         return redpac;  | 
|     }  | 
|   | 
|   | 
|     /**  | 
|      * 生产min和max之间的随机数,但是概率不是平均的,从min到max方向概率逐渐加大。  | 
|      * 先平方,然后产生一个平方值范围内的随机数,再开方,这样就产生了一种“膨胀”再“收缩”的效果。  | 
|      *  | 
|      * @param min  | 
|      * @param max  | 
|      * @return  | 
|      */  | 
|     static long xRandom(long min, long max) {  | 
|         return sqrt(nextLong(sqr(max - min)));  | 
|     }  | 
|   | 
|     /**  | 
|      *  | 
|      * @param totalStr  | 
|      *            红包总额  | 
|      * @param count  | 
|      *            红包个数  | 
|      * @param maxStr  | 
|      *            每个小红包的最大额  | 
|      * @param minStr  | 
|      *            每个小红包的最小额  | 
|      * @return 存放生成的每个小红包的值的数组  | 
|      */  | 
|     public static long[] generate(String totalStr, int count, String maxStr, String minStr) {  | 
|   | 
|         double mind = Double.parseDouble(minStr)*100;  | 
|         double maxd = Double.parseDouble(maxStr)*100;  | 
|         double totald = Double.parseDouble(totalStr)*100;  | 
|   | 
|         log.debug(mind+"========"+maxd);  | 
|   | 
|         long min = new Double(mind).longValue();  | 
|         long max = new Double(maxd).longValue();  | 
|         long total =new Double(totald).longValue();  | 
|   | 
|         long[] result = new long[count];  | 
|   | 
|         long average = total / count;  | 
|   | 
|         long a = average - min;  | 
|         long b = max - min;  | 
|   | 
|         //这样的随机数的概率实际改变了,产生大数的可能性要比产生小数的概率要小。  | 
|         //这样就实现了大部分红包的值在平均数附近。大红包和小红包比较少。  | 
|         long range1 = sqr(average - min);  | 
|         long range2 = sqr(max - average);  | 
|   | 
|         for (int i = 0; i < result.length; i++) {  | 
|             //因为小红包的数量通常是要比大红包的数量要多的,因为这里的概率要调换过来。  | 
|             //当随机数>平均值,则产生小红包  | 
|             //当随机数<平均值,则产生大红包  | 
|             if (nextLong(min, max) > average) {  | 
|                 // 在平均线上减钱  | 
| //                long temp = min + sqrt(nextLong(range1));  | 
|                 long temp = min + xRandom(min, average);  | 
|                 result[i] = temp;  | 
|                 total -= temp;  | 
|             } else {  | 
|                 // 在平均线上加钱  | 
| //                long temp = max - sqrt(nextLong(range2));  | 
|                 long temp = max - xRandom(average, max);  | 
|                 result[i] = temp;  | 
|                 total -= temp;  | 
|             }  | 
|         }  | 
|         // 如果还有余钱,则尝试加到小红包里,如果加不进去,则尝试下一个。  | 
|         while (total > 0) {  | 
|             for (int i = 0; i < result.length; i++) {  | 
|                 if (total > 0 && result[i] < max) {  | 
|                     result[i]++;  | 
|                     total--;  | 
|                 }  | 
|             }  | 
|         }  | 
|         // 如果钱是负数了,还得从已生成的小红包中抽取回来  | 
|         while (total < 0) {  | 
|             for (int i = 0; i < result.length; i++) {  | 
|                 if (total < 0 && result[i] > min) {  | 
|                     result[i]--;  | 
|                     total++;  | 
|                 }  | 
|             }  | 
|         }  | 
|         return result;  | 
|     }  | 
|   | 
|     static long sqrt(long n) {  | 
|         // 改进为查表?  | 
|         return (long) Math.sqrt(n);  | 
|     }  | 
|   | 
|     static long sqr(long n) {  | 
|         // 查表快,还是直接算快?  | 
|         return n * n;  | 
|     }  | 
|   | 
|     static long nextLong(long n) {  | 
|         return random.nextInt((int) n);  | 
|     }  | 
|   | 
|     static long nextLong(long min, long max) {  | 
|         return random.nextInt((int) (max - min + 1)) + min;  | 
|     }  | 
|   | 
|     public static void main(String[] args) {  | 
|            // System.out.println(roundByScale(new Double("1.10"),2));  | 
|         //double min_money=5; // 每个人最少能收到0.05元、  | 
|         //double max_money=20; // 每个人最少能收到0.05元、  | 
|         //randomPackage(100,10,40,2000);  | 
|         //long max = 2000;  | 
|         //long min = 40;  | 
|         //System.out.println(getStringRandom(6));  | 
|     }  | 
|     /**  | 
|      * 判断是否是手机号  | 
|      * @param tel 手机号  | 
|      * @return boolean true:是  false:否  | 
|      */  | 
|     public static boolean isMobile(String tel) {  | 
|         if (StringUtils.isEmpty(tel)){ return false;}  | 
|         return Pattern.matches(REGEX_MOBILE, tel);  | 
|     }  | 
|   | 
|   | 
|     /**  | 
|      * 使用java正则表达式去掉多余的.与0  | 
|      * @param s  | 
|      * @return  | 
|      */  | 
|     public static String subZeroAndDot(String s){  | 
|         if(StringUtils.isBlank(s)){  | 
|             return null;  | 
|         }  | 
|         if(s.indexOf(".") > 0){  | 
|             s = s.replaceAll("0+?$", "");//去掉多余的0  | 
|             s = s.replaceAll("[.]$", "");//如最后一位是.则去掉  | 
|         }  | 
|         return s;  | 
|     }  | 
|   | 
|     public static String getLowerLetterNumber(int length) {  | 
|         String str = "0123456789abcdefghijklmnopqrstuvwxyz0123456789";  | 
|         Random random = new Random();  | 
|         StringBuffer sb = new StringBuffer();  | 
|         for (int i = 0; i < length; ++i) {  | 
|             sb.append(str.charAt(random.nextInt(46)));  | 
|         }  | 
|         return sb.toString();  | 
|     }  | 
|   | 
| }  |