All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.acyou.leo.framework.util.NumberUtil Maven / Gradle / Ivy

package cn.acyou.leo.framework.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;

/**
 * @author youfang
 * @version [1.0.0, 2020/11/19]
 **/
@Slf4j
public class NumberUtil {
    /**
     * 单位进位,中文默认为4位即(万、亿)
     */
    public static int UNIT_STEP = 4;

    /**
     * 单位
     */
    public static String[] CN_UNITS = new String[]{"个", "十", "百", "千", "万", "十",
            "百", "千", "亿", "十", "百", "千", "万"};

    /**
     * 汉字
     */
    public static String[] CN_CHARS = new String[]{"零", "一", "二", "三", "四",
            "五", "六", "七", "八", "九"};


    /**
     * 将阿拉伯数字转换为中文数字
     * 

* 123 == 一二三 * * @param srcNum 数字 * @return 中文数字 */ public static String getCnNum(int srcNum) { StringBuilder descnnum = new StringBuilder(); if (srcNum <= 0) { descnnum = new StringBuilder("零"); } else { int singleDigit; while (srcNum > 0) { singleDigit = srcNum % 10; descnnum.insert(0, CN_CHARS[singleDigit]); srcNum /= 10; } } return descnnum.toString(); } /** * 数值转换为中文字符串(口语化) * * @param num 需要转换的数值 支持(int long double) * @param isColloquial 是否口语化。例如12转换为'十二'而不是'一十二'。 * @return str */ private static String cvt(String num, boolean isColloquial) { int integer, decimal; StringBuilder strs = new StringBuilder(32); String[] splitNum = num.split("\\."); //整数部分 integer = Integer.parseInt(splitNum[0]); //小数部分 decimal = Integer.parseInt(splitNum[1]); String[] integerResult = convert(integer, isColloquial); for (String str1 : integerResult) { strs.append(str1); } if (decimal == 0) { //小数部分为0时 return strs.toString(); } else { //例如5.32,小数部分展示三二,而不是三十二 String decimalResult = getCnNum(decimal); strs.append("点"); strs.append(decimalResult); return strs.toString(); } } /** * 将数值转换为中文 * * @param num 需要转换的数值 * @param isColloquial 是否口语化。例如12转换为'十二'而不是'一十二'。 * @return str[] */ public static String[] convert(long num, boolean isColloquial) { // 10以下直接返回对应汉字 if (num < 10) { // ASCII2int return new String[]{CN_CHARS[(int) num]}; } char[] chars = String.valueOf(num).toCharArray(); // 超过单位表示范围的返回空 if (chars.length > CN_UNITS.length) { return new String[]{}; } // 记录上次单位进位 boolean isLastUnitStep = false; // 创建数组,将数字填入单位对应的位置 ArrayList cnchars = new ArrayList<>(chars.length * 2); // 从低位向高位循环 for (int pos = chars.length - 1; pos >= 0; pos--) { char ch = chars[pos]; // ascii2int 汉字 String cnChar = CN_CHARS[ch - '0']; // 对应的单位坐标 int unitPos = chars.length - pos - 1; // 单位 String cnUnit = CN_UNITS[unitPos]; // 是否为0 boolean isZero = (ch == '0'); // 是否低位为0 boolean isZeroLow = (pos + 1 < chars.length && chars[pos + 1] == '0'); // 当前位是否需要单位进位 boolean isUnitStep = (unitPos >= UNIT_STEP && (unitPos % UNIT_STEP == 0)); // 去除相邻的上一个单位进位 if (isUnitStep && isLastUnitStep) { int size = cnchars.size(); cnchars.remove(size - 1); // 补0 if (!CN_CHARS[0].equals(cnchars.get(size - 2))) { cnchars.add(CN_CHARS[0]); } } // 单位进位(万、亿),或者非0时加上单位 if (isUnitStep || !isZero) { cnchars.add(cnUnit); isLastUnitStep = isUnitStep; } // 当前位为0低位为0,或者当前位为0并且为单位进位时进行省略 if (isZero && (isZeroLow || isUnitStep)) { continue; } cnchars.add(cnChar); isLastUnitStep = false; } Collections.reverse(cnchars); // 清除最后一位的0 int chSize = cnchars.size(); String chEnd = cnchars.get(chSize - 1); if (CN_CHARS[0].equals(chEnd) || CN_UNITS[0].equals(chEnd)) { cnchars.remove(chSize - 1); } // 口语化处理 if (isColloquial) { String chFirst = cnchars.get(0); String chSecond = cnchars.get(1); // 是否以'一'开头,紧跟'十' if (chFirst.equals(CN_CHARS[1]) && chSecond.startsWith(CN_UNITS[1])) { cnchars.remove(0); } } return cnchars.toArray(new String[]{}); } public static void main(String[] args) { System.out.println(NumberUtil.toUpperCaseAndColloquial(10)); System.out.println(NumberUtil.toUpperCaseAndColloquial(22)); } /** * 大写 *

* 口语化。例如12转换为'一十二'而不是'十二'。 * * @param num 数字 * @return {@link String} */ private static String toUpperCase(int num) { return cvt(String.valueOf(num), false); } /** * 大写和口语 *

* 口语化。例如12转换为'十二'而不是'一十二'。 * * @param num 数字 * @return {@link String} */ private static String toUpperCaseAndColloquial(int num) { return cvt(String.valueOf(num), true); } /** * 提供精确的加法运算
* 如果传入多个值为null或者空,则返回0 * * @param values 多个被加值 * @return 和 * @since 4.0.0 */ public static BigDecimal add(String... values) { if (ArrayUtils.isEmpty(values)) { return BigDecimal.ZERO; } String value = values[0]; BigDecimal result = toBigDecimal(value); for (int i = 1; i < values.length; i++) { value = values[i]; if (StringUtils.isNotBlank(value)) { result = result.add(toBigDecimal(value)); } } return result; } /** * 提供精确的减法运算
* 如果传入多个值为null或者空,则返回0 * * @param values 多个被减值 * @return 差 * @since 4.0.0 */ public static BigDecimal sub(String... values) { if (ArrayUtils.isEmpty(values)) { return BigDecimal.ZERO; } String value = values[0]; BigDecimal result = toBigDecimal(value); for (int i = 1; i < values.length; i++) { value = values[i]; if (StringUtils.isNotBlank(value)) { result = result.subtract(toBigDecimal(value)); } } return result; } /** * 提供精确的乘法运算
* 如果传入多个值为null或者空,则返回0 * * @param values 多个被乘值 * @return 积 * @since 4.0.0 */ public static BigDecimal mul(String... values) { if (ArrayUtils.isEmpty(values)) { return BigDecimal.ZERO; } BigDecimal result = new BigDecimal(values[0]); for (int i = 1; i < values.length; i++) { result = result.multiply(new BigDecimal(values[i])); } return result; } /** * 提供(相对)精确的除法运算,当发生除不尽的情况的时候,精确到小数点后10位,后面的四舍五入 * * @param v1 被除数 * @param v2 除数 * @return 两个参数的商 */ public static BigDecimal div(String v1, String v2) { return div(toBigDecimal(v1), toBigDecimal(v2), 2, RoundingMode.FLOOR); } /** * 提供(相对)精确的除法运算,当发生除不尽的情况时,由scale指定精确度 * * @param v1 被除数 * @param v2 除数 * @param scale 精确度,如果为负值,取绝对值 * @param roundingMode 保留小数的模式 {@link RoundingMode} * @return 两个参数的商 * @since 3.0.9 */ public static BigDecimal div(BigDecimal v1, BigDecimal v2, int scale, RoundingMode roundingMode) { Assert.notNull(v2, "Divisor must be not null !"); if (null == v1) { return BigDecimal.ZERO; } if (scale < 0) { scale = -scale; } return v1.divide(v2, scale, roundingMode); } /** * 数字转{@link BigDecimal}
* null或""或空白符转换为0 * * @param number 数字字符串 * @return {@link BigDecimal} * @since 4.0.9 */ public static BigDecimal toBigDecimal(String number) { try { number = parseNumber(number).toString(); } catch (Exception ignore) { // 忽略解析错误 } return StringUtils.isBlank(number) ? BigDecimal.ZERO : new BigDecimal(number); } /** * 将指定字符串转换为{@link Number} 对象 * * @param numberStr Number字符串 * @return Number对象 * @throws NumberFormatException 包装了{@link ParseException},当给定的数字字符串无法解析时抛出 * @since 4.1.15 */ public static Number parseNumber(String numberStr) throws NumberFormatException { try { return NumberFormat.getInstance().parse(numberStr); } catch (ParseException e) { final NumberFormatException nfe = new NumberFormatException(e.getMessage()); nfe.initCause(e); throw nfe; } } public static Integer parseInt(String s) { try { return Integer.valueOf(s); } catch (Exception e) { log.error("转换数字失败:{}", s); } return null; } public static Long parseLong(String s) { try { return Long.valueOf(s); } catch (Exception e) { log.error("转换数字失败:{}", s); } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy