package com.palmnest.application.core.util;

import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Random;
import java.util.regex.Pattern;

/**
 * 功能说明:
 * 提供高精度的运算支持.
 * 所以函数以double为参数类型，兼容int与float.
 * 创建时间: 2011 12 2 13:43:34
 *
 * @author admin
 */
public class NumberUtils {

	private NumberUtils() {

	}

	/**
	 * 精确的加法运算.
	 */
	public static double add(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(v1);
		BigDecimal b2 = new BigDecimal(v2);
		return b1.add(b2).doubleValue();
	}

	/**
	 * 精确的减法运算.
	 *
	 * @param v1 被减数
	 * @param v2 减数
	 */
	public static double subtract(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.subtract(b2).doubleValue();
	}

	/**
	 * 提供精确的乘法运算.
	 */
	public static double multiply(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(v1);
		BigDecimal b2 = new BigDecimal(v2);
		return b1.multiply(b2).doubleValue();
	}

	/**
	 * 提供精确的乘法运算，并对运算结果截位.
	 *
	 * @param scale 运算结果小数后精确的位数
	 */
	public static double multiply(double v1, double v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b1 = new BigDecimal(v1);
		BigDecimal b2 = new BigDecimal(v2);
		return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}


	/**
	 * 提供（相对）精确的除法运算.
	 *
	 * @see #divide(double, double, int)
	 */
	public static double divide(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(v1);
		BigDecimal b2 = new BigDecimal(v2);
		return b1.divide(b2).doubleValue();
	}

	/**
	 * 提供（相对）精确的除法运算.
	 * 由scale参数指定精度，以后的数字四舍五入.
	 *
	 * @param v1    被除数
	 * @param v2    除数
	 * @param scale 表示表示需要精确到小数点以后几位
	 */
	public static double divide(double v1, double v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}

		BigDecimal b1 = new BigDecimal(v1);
		BigDecimal b2 = new BigDecimal(v2);
		return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 提供精确的小数位四舍五入处理.
	 *
	 * @param v     需要四舍五入的数字
	 * @param scale 小数点后保留几位
	 */
	public static double round(double v, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b = new BigDecimal(v);
		return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 随机产生一个不大于max的随机整数
	 *
	 * @param max
	 * @return
	 */
	public static long randomNumber(long max) {
		long tmp = System.currentTimeMillis();
		long x = tmp % max;
		return x;
	}

	/**
	 * 正整数
	 *
	 * @param str
	 * @return
	 */
	public static boolean isInteger(String str) {
//	        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");  
//	        return pattern.matcher(str).matches();  

		Pattern pattern = Pattern.compile("[0-9]*");
		return pattern.matcher(str).matches();
	}

	public static boolean isNumeric(String str) {
		if (StringUtils.isBlank(str)) {
			return false;
		}

		int dotCount = 0;
		boolean result = true;
		for (int i = str.length(); --i >= 0; ) {
			char c = str.charAt(i);
			if (c == '.') {
				dotCount++;
				continue;
			}

			if (dotCount > 1) {
				result = false;
				break;
			}

			if (!Character.isDigit(str.charAt(i))) {
				result = false;
				break;
			}
		}
		return result;
	}

	/**
	 * @param sFenStr 金额（单位：分）
	 * @return 金额（单位：元）
	 * @desc 把金额由分转换成元
	 */
	public static String getYuanStr(String sFenStr) {
		String Y = "0";//元
		String J = "0";//角
		String F = "0";//分
		int len = sFenStr.length();
		if (len > 0) {
			F = sFenStr.substring(len - 1, len);
		}
		if (len > 1) {
			J = sFenStr.substring(len - 2, len - 1);
		}
		if (len > 2) {
			Y = sFenStr.substring(0, len - 2);
		}
		return Y + "." + J + F;
	}

	/**
	 * @desc 把金额由分转换成元 yb
	 */
	public static String getYuanStr2(String sFenStr) {
		if (sFenStr != null && !"".equals(sFenStr)) {
			int i = Integer.valueOf(sFenStr);
			double j = (double) i / 100;
			return j + "";
		}
		return "0";
	}


	//将20120626164400 转换位2012年06月26日 16:44:00
	public static String getFormatDate(String formateDate) {
		String str = "";
		String year = formateDate.substring(0, 4);
		String month = formateDate.substring(4, 6);
		String day = formateDate.substring(6, 8);
		String hour = formateDate.substring(8, 10);
		String min = formateDate.substring(10, 12);
		String second = formateDate.substring(12);
		return year + "年" + month + "月" + day + "日" + hour + ":" + min + ":" + second + "时";
	}

	/**
	 * 功能说明：将秒转换为分
	 *
	 * @return str
	 */
	public static String getFormateFen(String seconds) {
		if (seconds != null && !"".equals(seconds)) {
			int m = Integer.parseInt(seconds) / 60;
			return m + "";
		}
		return "";
	}

	/**
	 * 功能说明：将KB转换为M
	 *
	 * @return
	 */
	public static String getFormateM(String strkb) {
		if (strkb != null && !"".equals(strkb)) {
			//float m=Float.parseFloat(strkb)/1024;
			int m = Integer.parseInt(strkb) / 1024;
			return m + "";
		}
		return "";
	}

	/**
	 * 生成四位数验证码
	 *
	 * @return
	 */
	public static String getValidateCode() {
		Random ran = new Random();
		String str = "";
		for (int i = 0; i < 4; i++) {
			str += ran.nextInt(10);
		}
		return str;
	}

	static void adjustHeap(int[] array, int head, int tail) {
		int root = array[head];
		System.out.println("root:" + root);//第一次获取到的是7
		int i = 2 * head;
		while (i <= tail) {
			int max = array[i];//i=10 获取到的是12
			if (i + 1 <= tail)
				if (array[i + 1] > array[i]) {
					max = array[i + 1];
					i++;
				}
			if (root > max)
				//别手抖写成了return;
				break;
			else {
				array[i / 2] = array[i];
			}
			i *= 2;
		}
		array[i / 2] = root;
	}

	private static void swap(int[] array, int i, int j) {
		int tem = array[i];
		array[i] = array[j];
		array[j] = tem;
	}

	public static void main(String[] args) {
		int[] array = {0, 1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 6, 5};
		//建立建立节点个数为10的最大堆
		for (int i = 10 / 2; i >= 1; i--) {
			System.out.println("i:" + i);
			adjustHeap(array, i, 10);
		}
		//System.out.println(Arrays.toString(array));
		for (int i = 11; i < array.length; i++) {
			//如果这个元素小于堆顶，和堆顶交换，然后重新调整堆
			if (array[i] < array[1]) {
				swap(array, i, 1);
				adjustHeap(array, 1, 10);
			}

		}
		System.out.println(Arrays.toString(array));
		System.out.println("最小的10个数字为：");
		for (int i = 1; i <= 10; i++) {
			System.out.print(array[i] + " ");
		}
	}
}
