把大写的人民币金额转化为数字,不考虑角分,只精确到圆(整)

群里朋友发的一个面试题,看到之后,自己写的一个实现,基本测试通过,但没有经过大量测试,如果有什么问题,欢迎指出。代码如下:

package com.mmq;

/**
 * 请实现函数,把我们日常使用的大写的人民币金额转化为数字
 * 不考虑角分,只精确到圆(整),注该函数将被执行100万次,请考虑效率
 * @use 
 * @ProjectName gyjb
 * @Author <a href="mailto:mhmyqn@qq.com">mikan</a></br>
 * @Date 2013-3-27 上午01:01:45 </br>
 * @FullName com.mmq.MoneyString2Number.java </br>
 * @JDK 1.6.0 </br>
 * @Version 1.0 </br>
 */
public class MoneyString2Number {
    /**
     * 大写数字
     */
    private static final String NUMBER_CHARACTER_STRING = "零壹贰叁肆伍陆柒捌玖";
    /**
     * 基数字符
     */
    private static final String RADICES_CHARACTER_STRING = "拾佰仟万亿";
    /**
     * 基数数值
     */
    private static final int[] NUMBER_RADICES = new int[] { 10, 100, 1000, 10000, 100000000 };
    
    /**
     * 把大写的人民币金额转化为数字,不考虑角分,只精确到圆(整)
     * @param moneyString
     * @return
     */
    public static long transform(String moneyString) {
    	long result = 0;
    	int index = moneyString.indexOf("圆");
    	if (index != -1) {
    		moneyString = moneyString.substring(0, index + 1);//去掉角分
    	}
    	result = handleYi(moneyString);
    	return result;
    }
    
    /**
     * 按亿分成多个部分分别转化
     * @param moneyString
     * @return
     */
    private static long handleYi (String moneyString) {
    	long result = 0;
    	String[] monStringYiArr = moneyString.split("亿");
    	int length = monStringYiArr.length;
    	for (int i = 0; i < length; i++) {
    		String subMoneyString = monStringYiArr[i];
    		// 由于按'亿'分割之后,'亿'被去掉了,所以需要添加上
    		if (!(i == length - 1 && !moneyString.endsWith("亿"))) {
    			subMoneyString += "亿";
    		}
    		result += handleLing(subMoneyString);
    	}
    	return result;
    }
    
    /**
     * 按零分成多个部分分别转化
     * @param moneyString
     * @return
     */
    private static long handleLing(String moneyString) {
    	long result = 0;
    	String[] monStringArr = moneyString.split("零");
    	for (String subMoneyString : monStringArr) {
    		result += toNumber(subMoneyString);
    	}
    	return result;
    }
	
    /**
     * 把大写的人民币金额转化为数字
     * @param subMoneyString
     * @return
     */
	private static long toNumber(String subMoneyString) {
		long intermediateResult = 0;
		char[] moneyArr = subMoneyString.toCharArray();
		
		int index = 0;
		while (index < subMoneyString.length()) {
			if (moneyArr[index] == '零' || moneyArr[index] == '整' || moneyArr[index] == '圆') {
				index++;
				continue;
			}
			// 如果当前处理的位是基数位,则直接乘以之前的结果,继续处理下一位
			int indexOfRadices = RADICES_CHARACTER_STRING.indexOf(moneyArr[index]);
			if (indexOfRadices != -1) {
				intermediateResult = (intermediateResult == 0 ? 1 : intermediateResult) * NUMBER_RADICES[indexOfRadices];
				index++;
				continue;
			}
			
			// 处理数字位
			int indexOfDigit = NUMBER_CHARACTER_STRING.indexOf(moneyArr[index]);
			long tmp = indexOfDigit;
			// 如果要处理的金额字符串只有一位数字,直接返回这位数字
			if (subMoneyString.length() == 1) {
				return indexOfDigit;
			}
			
			// 当前数字位的一下位是 '整' 或 '圆',则返回结果
			int indexOfRadices_next = RADICES_CHARACTER_STRING.indexOf(moneyArr[index + 1]);
			if (moneyArr[index + 1] == '整' || moneyArr[index + 1] == '圆') {
				intermediateResult += tmp;
				return intermediateResult;
			}
			
			// 如果当前数字位的下一位是基数位,则先计算结果,
			// 如果基数位是'拾'且基数位的一下位是数字,则继续处理下一位
			if (indexOfRadices_next != -1) {
				tmp *= NUMBER_RADICES[indexOfRadices_next];
				if ((index + 2) < subMoneyString.length()) {
					int indexOfDigit_next = NUMBER_CHARACTER_STRING.indexOf(moneyArr[index + 2]);
					if (moneyArr[index + 1] == '拾' && indexOfDigit_next != -1) {
						tmp += indexOfDigit_next;
						index++;
					}
				}
				index += 2;
				intermediateResult += tmp;
			}
			
		}
		return intermediateResult;
	}
	
	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		System.out.println(transform("壹万贰仟叁佰肆拾伍"));//12345
		System.out.println(transform("佰万"));//1000000
		System.out.println(transform("壹佰"));//100
		System.out.println(transform("壹"));//1
		System.out.println(transform("壹亿"));//100000000
		System.out.println(transform("壹佰万零叁佰肆拾伍圆整"));//1000345
		System.out.println(transform("壹佰亿零叁仟肆佰伍拾陆圆整"));//10000003456
		System.out.println(transform("壹万贰仟叁佰肆拾亿零肆拾伍万零壹圆整"));//1234000450001
		System.out.println(transform("壹拾亿零壹圆整"));//1000000001
		System.out.println(transform("壹佰贰拾叁万圆整"));//1230000
		System.out.println(transform("壹亿贰仟叁佰肆拾伍万圆整"));//123450000
		System.out.println(transform("贰万亿"));//2000000000000
		System.out.println(transform("零"));//0
		System.out.println("用时:" + (System.currentTimeMillis() - start) + "毫秒");
	}
}

测试结果如下:

12345
1000000
100
1
100000000
1000345
10000003456
1234000450001
1000000001
1230000
123450000
2000000000000
0
用时:2毫秒


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我明白了。关于你的问题,可以编写一个MySQL自定义函数来实现人民币大写数字的功能。下面是一个简单的MySQL自定义函数实现方式: ``` DELIMITER $$ CREATE FUNCTION rmb_to_number(rmb_str VARCHAR(255)) RETURNS DECIMAL(12,2) BEGIN DECLARE number DECIMAL(12,2); DECLARE digit DECIMAL(12,2); DECLARE unit VARCHAR(10); DECLARE rmb_len INT; DECLARE i INT; SET rmb_str = TRIM(rmb_str); IF rmb_str = '' THEN RETURN NULL; END IF; SET rmb_str = REPLACE(rmb_str, ' ', ''); IF rmb_str REGEXP '^(-)?[0-9]+(.[0-9]{1,2})?$' THEN RETURN CAST(rmb_str AS DECIMAL(12,2)); END IF; SET number = 0; SET digit = 1; SET rmb_len = LENGTH(rmb_str); IF rmb_len < 2 THEN RETURN NULL; END IF; IF rmb_str REGEXP '^(-)?[壹贰叁肆伍陆柒捌玖拾佰仟万亿元角分]+$' THEN SET i = 1; WHILE i <= rmb_len DO SET unit = SUBSTR(rmb_str, i, 1); IF unit IN ('壹', '一') THEN SET number = number + digit; ELSEIF unit IN ('贰', '两', '二') THEN SET number = number + digit * 2; ELSEIF unit = '叁' THEN SET number = number + digit * 3; ELSEIF unit = '肆' THEN SET number = number + digit * 4; ELSEIF unit = '伍' THEN SET number = number + digit * 5; ELSEIF unit = '陆' THEN SET number = number + digit * 6; ELSEIF unit = '柒' THEN SET number = number + digit * 7; ELSEIF unit = '捌' THEN SET number = number + digit * 8; ELSEIF unit = '玖' THEN SET number = number + digit * 9; ELSEIF unit = '拾' THEN SET digit = 10; ELSEIF unit = '佰' THEN SET digit = 100; ELSEIF unit = '仟' THEN SET digit = 1000; ELSEIF unit = '万' THEN SET digit = 10000; SET number = number * digit; SET digit = 1; ELSEIF unit = '亿' THEN SET digit = 100000000; SET number = number * digit; SET digit = 1; ELSEIF unit IN ('元', '') THEN SET digit = 1; ELSEIF unit = '角' THEN SET number = number + digit / 10; ELSEIF unit = '分' THEN SET number = number + digit / 100; END IF; SET i = i + 1; END WHILE; RETURN number; ELSE RETURN NULL; END IF; END$$ DELIMITER ; ``` 这个自定义函数可以将形如“叁仟贰佰元肆角伍分”这样的人民币大写转换为对应的数字金额,比如“3204.50”。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值