Java tutorial
/* * Copyright (C) 2008 feilong * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sunchenbin.store.feilong.core.lang; import java.io.Serializable; import java.math.BigDecimal; import java.math.RoundingMode; import com.sunchenbin.store.feilong.core.bean.ConvertUtil; import com.sunchenbin.store.feilong.core.text.NumberFormatUtil; import com.sunchenbin.store.feilong.core.util.Validator; /** * ?{@link Integer},{@link Long},{@link BigDecimal}?. * * <h3>{@link RoundingMode#HALF_UP} {@link Math#round(double)}:</h3> * * <blockquote> * <p style="color:red"> * ?{@link RoundingMode#HALF_UP} -2.5 ??-3, {@link Math#round(double) Math.round(-2.5)} -2 * </p> * </blockquote> * * <h3>{@link Double}{@link BigDecimal}:</h3> * * <blockquote> * <p> * double ? BigDecimal,?? BigDecimal.valueOf(double),?new BigDecimal(double),?? JDK API * </p> * <ol> * <li>new BigDecimal(0.1) {@code ==>} 0.1000000000000000055511151231257827021181583404541015625</li> * <li>BigDecimal.valueOf(0.1) {@code ==>} 0.1</li> * </ol> * <p> * Effective Java??,floatdouble???,? {@link java.math.BigDecimal} * </p> * </blockquote> * * <h3><a name="RoundingMode">JAVA 8??:</a></h3> * * <blockquote> * <table border="1" cellspacing="0" cellpadding="4"> * <tr style="background-color:#ccccff"> * <th align="left"></th> * <th align="left"></th> * </tr> * <tr valign="top"> * <td>{@link RoundingMode#UP}</td> * <td>??. ????,?????0??.</td> * </tr> * <tr valign="top" style="background-color:#eeeeff"> * <td>{@link RoundingMode#DOWN}</td> * <td>???,????,???,??.</td> * </tr> * <tr valign="top"> * <td>{@link RoundingMode#CEILING}</td> * <td>??? ??? ???.<br> * ,?ROUND_UP,<br> * ,?ROUND_DOWN.<br> * <span style="color:red">Math.round()?.</span></td> * </tr> * <tr valign="top" style="background-color:#eeeeff"> * <td>{@link RoundingMode#FLOOR}</td> * <td>??? ??? ???.<br> * ,?ROUND_DOWN<br> * ,?ROUND_UP.</td> * </tr> * <tr valign="top"> * <td>{@link RoundingMode#HALF_UP}</td> * <td>?,?.<br> * ?(5).<span style="color:red">??</span>.</td> * </tr> * <tr valign="top" style="background-color:#eeeeff"> * <td>{@link RoundingMode#HALF_DOWN}</td> * <td>?,?(5?). 5??.</td> * </tr> * <tr valign="top"> * <td>{@link RoundingMode#HALF_EVEN}</td> * <td>?,?. <br> * ?;?,??,?,??. <br> * ???1?,???: <br> * {@code 1.15 return 1.2} {@code 1.25 return 1.2}</td> * </tr> * <tr valign="top" style="background-color:#eeeeff"> * <td>{@link RoundingMode#UNNECESSARY}</td> * <td>?</td> * </tr> * </table> * </blockquote> * * @author feilong * @version 1.4.0 201583 ?3:06:20 * @see Integer * @see Long * @see BigDecimal * @see Number * @see NumberPattern * @see RoundingMode * @see org.apache.commons.lang3.math.NumberUtils * @since 1.4.0 */ public final class NumberUtil { /** Don't let anyone instantiate this class. */ private NumberUtil() { //AssertionError?. ?????. ???. //see Effective Java 2nd throw new AssertionError("No " + getClass().getName() + " instances for you!"); } /** * ? {@link RoundingMode#HALF_UP},?,?. * * <p style="color:red"> * ?{@link RoundingMode#HALF_UP} -2.5 ??-3, Math.round(-2.5) -2 * </p> * * @param number * number,?,?number * @return ?{@link RoundingMode#HALF_UP},?,?<br> * isNotNullOrEmpty(number)null * @see <a href="#RoundingMode">JAVA 8??</a> */ public static BigDecimal toNoScale(Serializable number) { RoundingMode roundingMode = RoundingMode.HALF_UP; return toNoScale(number, roundingMode); } /** * To no scale. * * @param number * number,?,?number * @param roundingMode * ? {@link RoundingMode} * @return {@link RoundingMode},?,?<br> * isNotNullOrEmpty(number)null {@link RoundingMode},?,? * @see <a href="#RoundingMode">JAVA 8??</a> * @since 1.0.7 */ public static BigDecimal toNoScale(Serializable number, RoundingMode roundingMode) { if (Validator.isNullOrEmpty(number)) { return null; } //int?long?double?stringBigDecimal.double?, //BigDecimal,String??. BigDecimal bigDecimal = ConvertUtil.toBigDecimal(number); return setScale(bigDecimal, 0, roundingMode); } // *********************************************************************************** // [start]Divide /** * one/two,? ?,???toNoScale?. * <p> * two 0,one<br> * ?one/two,??. * * @param one * * @param two * ,?BigDecimal?? * @return two 0,one<br> * ?one/two,? ? */ public static BigDecimal getDivideNoScaleValue(BigDecimal one, Serializable two) { return getDivideValue(one, two, 0); } /** * ,? {@link NumberPattern#PERCENT_WITH_NOPOINT}. * * @param current * ?? * @param total * ? * @return 50% 56% 58%??? * @see NumberPattern * @since 1.0.7 */ public static String getProgress(Number current, Number total) { String numberPattern = NumberPattern.PERCENT_WITH_NOPOINT; return getProgress(current, total, numberPattern); } /** * . * * <pre> * {@code * Example 1: * NumberUtil.getProgress(5, 5, "##%") * return 100% * * Example 2: * NumberUtil.getProgress(2, 3, "#0.0%") * return 66.7% * } * </pre> * * @param current * ?? * @param total * ? * @param numberPattern * the number pattern {@link NumberPattern} * @return ?numberPattern 50.5%,100%..... * @see NumberPattern * @since 1.0.7 */ public static String getProgress(Number current, Number total, String numberPattern) { if (null == current) { throw new NullPointerException("current is null"); } if (null == total) { throw new NullPointerException("total is null"); } if (current.intValue() <= 0) { throw new IllegalArgumentException("current can not <=0"); } if (total.intValue() <= 0) { throw new IllegalArgumentException("total can not <=0"); } if (current.doubleValue() > total.doubleValue()) { throw new IllegalArgumentException("current can not > total"); } // XXX int scale = 8; BigDecimal bigDecimalCurrent = ConvertUtil.toBigDecimal(current); BigDecimal divideValue = getDivideValue(bigDecimalCurrent, total, scale); return toString(divideValue, numberPattern); } /** * one/two,? {@link RoundingMode#HALF_UP},??. * * <p> * two0,one<br> * ?one/two,?,??. * </p> * * @param one * * @param two * ,?BigDecimal?? * @param scale * ? BigDecimal ,?? * @return two 0,one<br> * ?one/two,? {@link RoundingMode#HALF_UP},?? * @see <a href="#RoundingMode">JAVA 8??</a> * @see java.math.RoundingMode#HALF_UP * @see java.math.BigDecimal#ROUND_HALF_UP */ public static BigDecimal getDivideValue(BigDecimal one, Serializable two, int scale) { RoundingMode roundingMode = RoundingMode.HALF_UP; return getDivideValue(one, two, scale, roundingMode); } /** * one/two,?,??. * * <p> * two 0,one<br> * ?one/two,?,??. * </p> * * <p> * <b>?:</b> <span style="color:red">?one.divide(two),?? exception:Non-terminating decimal expansion; no exact representable decimal * result</span><br> * scaleroundingMode,?????. * </p> * * @param one * * @param two * ,?BigDecimal?? * @param scale * ? BigDecimal ,?? * @param roundingMode * ? {@link RoundingMode} * @return two 0,one<br> * ?one/two,??? {@link RoundingMode},?? * @see <a href="#RoundingMode">JAVA 8??</a> * @since 1.0.7 */ public static BigDecimal getDivideValue(BigDecimal one, Serializable two, int scale, RoundingMode roundingMode) { if (Validator.isNullOrEmpty(roundingMode)) { throw new NullPointerException("the roundingMode is null or empty!"); } String zero = "0"; if (!isSpecificNumber(two, zero)) { // ?one.divide(two) // ?? exception:Non-terminating decimal expansion; no exact representable decimal result // scaleroundingMode,?????. BigDecimal divisor = ConvertUtil.toBigDecimal(two); return one.divide(divisor, scale, roundingMode); } return one; } // [end] // [start]Multiply /** * . * * @param one * * @param two * * @param scale * ,??,? * @return <br> * if isNotNullOrEmpty(two) return one * @see #getMultiplyValue(BigDecimal, Serializable) * @see #setScale(BigDecimal, int) */ public static BigDecimal getMultiplyValue(BigDecimal one, Serializable two, int scale) { BigDecimal result = getMultiplyValue(one, two); return setScale(result, scale); } /** * multiply value. * * <p> * scale: (this.scale() + multiplicand.scale()). * </p> * * @param one * * @param two * * @return <br> * if isNotNullOrEmpty(two) return one * @see java.math.BigDecimal#multiply(BigDecimal) * @since 1.0.8 */ public static BigDecimal getMultiplyValue(BigDecimal one, Serializable two) { if (Validator.isNullOrEmpty(two)) { return one; } BigDecimal multiplicand = ConvertUtil.toBigDecimal(two); return one.multiply(multiplicand); } /** * multiply value. * * <p> * scale: (this.scale() + multiplicand.scale()). * </p> * * @param one * * @param two * * @return <br> * if isNotNullOrEmpty(two) return one * @see #getMultiplyValue(BigDecimal, Serializable) * @since 1.2.1 */ public static BigDecimal getMultiplyValue(Number one, Serializable two) { return getMultiplyValue(ConvertUtil.toBigDecimal(one), two); } // [end] // [start]Add /** * ,null. * * @param one * * @param two * * @return <ul> * <li> null,null</li> * <li>null,?null,,?BigDecimal </li> * <li>?null,null,</li> * <li>(?), +</li> * </ul> * @since 1.0 */ public static BigDecimal /* <T> T */ getAddValue(Number one, Number two) { // null,null if (Validator.isNullOrEmpty(one) && Validator.isNullOrEmpty(two)) { return null; } // ?null,null, if (!Validator.isNullOrEmpty(one) && Validator.isNullOrEmpty(two)) { // ObjectUtil.toT(value, class1) return ConvertUtil.toBigDecimal(one); } BigDecimal augend = ConvertUtil.toBigDecimal(two); // null,?null,,?BigDecimal if (Validator.isNullOrEmpty(one) && !Validator.isNullOrEmpty(two)) { return augend; } // (?), + return ConvertUtil.toBigDecimal(one).add(augend); } /** * ?(null). * * @param numbers * the numbers * @return the value * @since 1.2.1 */ public static BigDecimal getAddValue(Number... numbers) { BigDecimal returnValue = BigDecimal.ZERO; for (Number number : numbers) { if (Validator.isNotNullOrEmpty(number)) { BigDecimal bigDecimal = ConvertUtil.toBigDecimal(number); returnValue = returnValue.add(bigDecimal); } } return returnValue; } // [end] /** * ?? ??? 0.0,0.5,1.0,1.5,2.0,2.5.... * * <p> * * </p> * * @param value * * @return 0.0,0.5,1.0,1.5,2.0,2.5....... */ public static String toPointFive(Number value) { if (Validator.isNullOrEmpty(value)) { throw new NullPointerException("value can't be null/empty!"); } long avgRankLong = Math.round(Double.parseDouble(value.toString()) * 2); BigDecimal avgBigDecimal = BigDecimal.valueOf((double) (avgRankLong) / 2); return setScale(avgBigDecimal, 1).toString(); } /** * ?, {@link NumberFormatUtil#format(Number, String)} . * * <h3>:</h3> * * <blockquote> * * <pre> * {@code * * ?,??, 0.24?24% * NumberUtil.toString(0.24f, NumberPattern.PERCENT_WITH_NOPOINT) * * ?,??, 0.24?24.00% * NumberUtil.toString(0.24f, NumberPattern.PERCENT_WITH_2POINT) * } * </pre> * * </blockquote> * * @param value * * @param pattern * {@link NumberPattern} * @return ?? * * @see NumberFormatUtil#format(Number, String) */ public static String toString(Number value, String pattern) { return NumberFormatUtil.format(value, pattern); } // ***************************************************************************************************** /** * int??16. * * @param i * int * @return int??16 */ public static String intToHexString(int i) { return Integer.toHexString(i); } /** * 16?int. * * @param hexString * 16 * @return int */ public static int hexStringToInt(String hexString) { return Integer.parseInt(hexString, 16); } /** * Object value,?. * * <p> * value ?BigDecimal,specificNumber ?BigDecimal ,BigDecimal compareTo,<br> * 0 ,true. * </p> * * @param value * Object value, Number String * @param specificNumber * * @return value ?BigDecimal,specificNumber ?BigDecimal ,BigDecimal compareTo,<br> * 0 ,true */ public static boolean isSpecificNumber(Serializable value, String specificNumber) { if (Validator.isNullOrEmpty(value)) { return false; } String valueString = value.toString(); // Number /String if (value instanceof Number || value instanceof String) { BigDecimal bigDecimal = ConvertUtil.toBigDecimal(valueString); int i = bigDecimal.compareTo(ConvertUtil.toBigDecimal(specificNumber)); return i == 0; } return false; } /** * ? ??? {@link RoundingMode#HALF_UP} ??. * * <p> * ?>=0.5? ??<br> * </p> * * <p style="color:red"> * ?{@link RoundingMode#HALF_UP} -2.5 ??-3, Math.round(-2.5) -2 * </p> * * @param number * number * @param scale * ?? * @return the big decimal * @see <a href="#RoundingMode">JAVA 8??</a> * @see java.math.RoundingMode#HALF_UP * @see java.math.BigDecimal#ROUND_HALF_UP */ private static BigDecimal setScale(BigDecimal number, int scale) { RoundingMode roundingMode = RoundingMode.HALF_UP; return setScale(number, scale, roundingMode); } /** * . * * @param number * number * @param scale * ?? * @param roundingMode * ? {@link RoundingMode} ?: {@link <a href="#RoundingMode">JAVA 8??</a>} * @return the big decimal * @see <a href="#RoundingMode">JAVA 8??</a> */ private static BigDecimal setScale(BigDecimal number, int scale, RoundingMode roundingMode) { return number.setScale(scale, roundingMode); } }