Java数字金额大写转换

Java中,将数字价格转换为中文大写通常涉及几个步骤,包括将数字分解为各个部分(如个位、十位、百位等),然后根据这些部分转换为对应的中文大写数字,并添加适当的单位(如元、角、分)。

我这边按照正式合同要求到角也加了整数,然后小数点后两位以后的数字将会直接舍弃

 /** 中文大写数字 */
  private static final char[] CNS = new char[] {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};

  /** 次级单位 */
  private static final char[] LOW = new char[] {'拾', '佰', '仟'};

  /** 一级单位 */
  private static final char[] HIGH = new char[] {'万', '亿'};

  /** 基本单位 */
  private static final char[] UNIT = new char[] {'元', '角', '分'};

  /** 整 or 正 */
  private static final char PERFECT = '整';

  /** 字符0 */
  private static final char ZERO = '0';

  /** 字符串0 */
  private static final String ZERO_STRING = "0";

  /** 零元整 */
  private static final String PERFECT_ZERO = "零元整";

  /** 负号 */
  private static final char NEGATIVE_SYMBOL = '-';

  /** 中文负字 */
  private static final String NEGATIVE_CN = "负";

/**
   * 阿拉伯数字转中文大写数字,小数点后两位以后的数字将会被直接舍弃
   *
   * @param input 非负阿拉伯数字
   * @return 中文大写数字,转换失败返回null
   */
  public static String convert(String input) {
    if (!isValidNumber(input)) {
      if (isScientificNotation(input)) {
        input = new BigDecimal(input).toPlainString();
      } else {
        return null;
      }
    }
    // 处理负值
    boolean isNegative = false;
    if (input.charAt(0) == NEGATIVE_SYMBOL) {
      isNegative = true;
      input = input.substring(1);
    }
    if (Objects.equals(input, ZERO_STRING)) {
      return PERFECT_ZERO;
    }
    // 移除开头的无效0
    for (int i = 0; i < input.length(); ++i) {
      char c = input.charAt(i);
      if (c == '.') {
        input = input.substring(i - 1);
        break;
      } else if (c != ZERO) {
        input = input.substring(i);
        break;
      }
    }
    // 转换整数部分
    String[] arrays = input.split("\\.");
    input = arrays[0];
    char[] chars = input.toCharArray();
    StringBuilder res = new StringBuilder();
    int idx = chars.length - 1;
    int lowIdx = idx % 4 - 1;
    int highIdx = idx / 4 == 0 ? -1 : (idx / 4) % 2 != 0 ? 0 : 1;
    boolean needToAddZero = false;
    boolean canAddNextHigh = false;
    for (char c : chars) {
      if (c == ZERO) {
        needToAddZero = true;
      } else {
        if (needToAddZero) {
          res.append(CNS[0]);
          needToAddZero = false;
        }
        res.append(CNS[c - ZERO]);
        if (lowIdx != -1) {
          res.append(LOW[lowIdx]);
        }
        canAddNextHigh = true;
      }
      if (--lowIdx == -2) {
        lowIdx = 2;
      }
      if (idx % 4 == 0 && idx != 0) {
        if (canAddNextHigh) {
          res.append(HIGH[highIdx]);
          canAddNextHigh = false;
          needToAddZero = false;
        }
        if (--highIdx == -1) {
          highIdx = 1;
        }
      }
      --idx;
    }
    if (res.length() == 0) {
      res.append(CNS[0]);
    }
    res.append(UNIT[0]);
    // 转换小数部分
    int len = res.length();
    boolean hasDecimalPart = arrays.length == 2;
    if (hasDecimalPart) {
      // 小数点后2位以后的直接舍弃
      char[] chs = arrays[1].toCharArray();
      int count = chs.length;
      if (count == 1) {
        if (chs[0] != ZERO) {
          res.append(CNS[chs[0] - ZERO]).append(UNIT[1]);
        }
      } else {
        if (chs[0] != ZERO || chs[1] != ZERO) {
          res.append(CNS[chs[0] - ZERO]);
          if (chs[0] != ZERO) {
            res.append(UNIT[1]);
          }
          if (chs[1] != ZERO) {
            res.append(CNS[chs[1] - ZERO]).append(UNIT[2]);
          }
        }
      }
    }
    // 添加“整”字逻辑
    if (len == res.length() || (hasDecimalPart && res.charAt(res.length() - 1) == '角')) {  // 修改点
      res.append(PERFECT);  // 修改点
    }
    return PERFECT_ZERO.equals(res)
        ? PERFECT_ZERO
        : isNegative ? NEGATIVE_CN.concat(res.toString()) : res.toString();
  }

  public static void main(String[] args) {
    System.out.println(convert("0.00"));
    System.out.println(convert("100"));
    System.out.println(convert("100.00"));
    System.out.println(convert("100.01"));
    System.out.println(convert("1000.00"));
    System.out.println(convert("10000"));
    System.out.println(convert("10000.002"));
    System.out.println(convert("106912.00"));
    System.out.println(convert("10010000.00"));
    System.out.println(convert("17056086.6"));
    System.out.println(convert("17056086.65"));
  }

  /**
   * 是否是合法的阿拉伯数字
   *
   * @param input 需要检验的阿拉伯数字
   * @return 合法返回true,反之返回false
   */
  public static boolean isValidNumber(String input) {
    return StringUtils.isNotBlank(input) && input.matches("^-?[0-9]+(\\.[0-9]+)?$");
  }

  /**
   * 是否科学记数法
   *
   * @param input 需要检验的阿拉伯数字
   * @return 合法返回true,反之返回false
   */
  public static boolean isScientificNotation(String input) {
    return StringUtils.isNotBlank(input)
        && input.matches("^([+|-]?\\d+(.{0}|.\\d+))[Ee]([+|-]?\\d+)$");
  }

输出内容为:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值