`

人民币金额小写转换大写

阅读更多

     准备跳槽,找了网上的笔试题看了一下, 发现常考金额转换成大写的编程题。

网上给出的答案不太满意,iteye上搜索一下, 有不少人给出一些例子,很多转换结果不准确,还有人说不到30行代码就能完成,我一看代码,天书而已, 立马摒弃掉了。
     思考一番, 也写了下代码,测试也没问题,有兴趣的朋友可以提提意见。

 

 

     网上其他人的代码大多是只能转换整数最多13位,一般转换方案都是下面两种(第一种看完都不想再当码农了 ,第二种看似挺好, 但是处理起来截取字符串麻烦,容易因规则太复杂找不到出路):

String capUnit[] = {'万','亿','万','圆',''};     
String capDigit[][] = { {''},{''},{'角','分',''},{''} {'仟','佰','拾',''}};     
String capNum[]={'零','壹','贰','叁','肆','伍','陆','柒','捌','玖'};     
 
String big = "壹贰叁肆伍陆柒捌玖";
String digit = new Array("圆拾佰仟万拾佰仟亿拾佰仟万","角分");

 

  
   我自己写的代码方案与第一种差不多,思路绝对清晰明了,代码里写得很清楚:

  

package com.liany.demo.translate;

import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
 * 金额转换成大写
 * @author modiliany
 * @date 2012-04-10
 */
public class TransformMoney {
	
/*
以下摘自百度百科:http://baike.baidu.com/view/359995.htm
大写数字规则
	中文大写金额数字应用正楷或行书填写,如壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整(正)等字样。不得用一、二(两)、三、四、五、六、七、八、九、十、廿、毛、另(或0)填写,不得自造简化字。如果金额数字书写中使用繁体字,如贰、陆、亿、万、圆的,也可。
	中文大写金额数字到"元"为止的,在"元"之后,应写"整"(或"正")字,在"角"之后,可以不写"整"(或"正")字。大写金额数字有"分"的,"分"后面不写"整"(或"正")字。
	中文大写金额数字前应标明"人民币"字样,大写金额数字有"分"的,"分"后面不写"整"(或"正")字。
	中文大写金额数字前应标明"人民币"字样,大写金额数字应紧接"人民币"字样填写,不得留有空白。大写金额数字前未印"人民币"字样的,应加填"人民币"三字。在票据和结算凭证大写金额栏内不得预印固定的"仟、佰、拾、万、仟、佰、拾、元、角、分"字样。
	阿拉伯数字小写金额数字中有"0"时,中文大写应按照汉语语言规律、金额数字构成和防止涂改的要求进行书写。举例如下:
	阿拉伯数字中间有"0"时,中文大写要写"零"字,如¥1409.50,应写成人民币壹仟肆佰零玖元伍角。
	阿拉伯数字中间连续有几个"0"时,中文大写金额中间可以只写一个"零"字,如¥6007.14,应写成人民币陆仟零柒元壹角肆分。
	阿拉伯金额数字万位和元位是"0",或者数字中间连续有几个"0",万位、元位也是"0",但千位、角位不是"0"时,中文大写金额中可以只写一个零字,也可以不写"零"字。如¥1680.32,应写成人民币壹仟陆佰捌拾元零叁角贰分,或者写成人民币壹仟陆佰捌拾元叁角贰分,又如¥107000.53,应写成人民币壹拾万柒仟元零伍角叁分,或者写成人民币壹拾万零柒仟元伍角叁分。
	阿拉伯金额数字角位是"0",而分位不是"0"时,中文大写金额"元"后面应写"零"字。如¥16409.02,应写成人民币壹万陆仟肆佰零玖元零贰分;又如¥325.04,应写成人民币叁佰贰拾伍元零肆分。 
*/
	
	static final String big = "零壹贰叁肆伍陆柒捌玖";		//大写
	static final String[] units = {"仟佰拾", "角分"};	//单位

	
	/**
	 * 双精度浮点数转换成字符串
	 * 注:
	 * 1、如果直接用String.toString(double d)方法,超大数额会出现科学计数法的字符串;
	 * 2、如果整数部分超过15位数,低位部分可能出现误差,所以不支持超过15位整数的数值,
	 *   一般数据库设计金额字段时都不会超过15位整数,如oracle用Number(18,3)的类型表示,整数部分最多15位,小数点后保留3位有效数字。
	 */
	public static String getDecimalStr(double d){
		//设置小数点后的精度,保留两位
		/*四舍五入结果参考:
		0.005,//0.01入
		0.015,//0.01舍
		0.025,//0.03入
		0.035,//0.04入
		0.045,//0.04舍
		0.055,//0.06入(前一位是5则入)
		*/
		String str = new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
		
		/*
		//经过测试,以下三种方法都是可以用的:
		//或1:
		String str = new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString();

		//或2:
		DecimalFormat format = new DecimalFormat();
		format.applyPattern("#################0.00");
		String str = format.format(d);
		
		//或3:
		DecimalFormat decimalFormat = new DecimalFormat();  
		decimalFormat.setMinimumFractionDigits(2);  
		decimalFormat.setMaximumFractionDigits(2);  
		decimalFormat.setGroupingUsed(false);  
		decimalFormat.setMaximumIntegerDigits(15);  
		decimalFormat.setMinimumIntegerDigits(15);  
		str=decimalFormat.format(d); 
		*/
		
		//如果结果是整数,则去掉尾巴
		if(str.endsWith(".00")){
			str = str.replace(".00", "");
		}
		return str;
	}
	
	/**
	 * 金额是double类型的要先转换成字符串
	 * @param money 金额
	 */
	public static String transform(double money){
		String moneyStr = getDecimalStr(money);
		return transform(moneyStr);
	}
	
	/**
	 * 金额转换成大字
	 * 我的思路:
	 * 1、double数值转换成数值字符串
	 * 2、处理整数部分:
	 *   填充到16位,不足16位则前面补'0',然后右起分成四组,每组根据"x仟x佰x拾x"的规则转换成大写,若该组为"0000"则结果是"零";
	 *   对这四组结果从高位到低位拼接起来,规则:[组4]万[组3]亿[组2]万[组1]圆。
	 * 3、处理小数部分(不多说)
	 */
	public static String transform(String moneyStr){
		String[] parts = moneyStr.split("\\.");	//区别整数、小数部分
		String result = "";
		
		//处理整数部分
		int length = parts[0].length();	//整数部分的位数
		if(length>15){
			return "金额太大,不能处理整数部分超过15位的金额!";
		}
		String intPart = parts[0];
		
		//填充到16位,因为是分4组,每组4个数字
		while(intPart.length()<16){
			intPart = '0' + intPart;
		}
		//共分四组,右起四位一组,例如:0001,2003,0030,3400
		String[] groups = new String[4]; 
		for(int i=0; i < groups.length; i++){
			int start = intPart.length()-(i+1)*4;	//开始位置
			int end = intPart.length()-i*4;			//结束位置
			groups[i] = intPart.substring(start, end);
			groups[i] = transformGroup(groups[i]);	//当前组的四位数字转换成大写
		}
		
		//对这四组结果从高位到低位拼接起来,规则:[组4]万[组3]亿[组2]万[组1]圆
		for(int i=groups.length-1; i>=0; i--){
			if(i==3){	//第四组:万亿级
				if(!"零".equals(groups[i])){
					result += groups[i] + "万";
				}
			}else if(i==2){	//第三组:亿级
				if(!"零".equals(groups[i])){
					result += groups[i] + "亿";
				}else{
					if(result.length()>0){
						result += "亿";
					}
				}
			}else if(i==1){	//第二组:万级
				if(!"零".equals(groups[i])){
					result += groups[i] + "万";
				}else if(!groups[i].startsWith("零")){
					result += groups[i];
				} 
			}else{	//第一组:千级
				if(!"零".equals(groups[i]) || result.length()==0){
					result += groups[i];
				}
				result += "圆";
			}
		}
		if(!"零圆".equals(result) && result.startsWith("零")){
			result = result.substring(1, result.length()); //最前面的可能出现的“零”去掉
		}

		//处理小数部分
		if(parts.length==2){
			String decimalPart = parts[1];	//小数部分
			for(int i=0; i < decimalPart.length();i++){
				int num = Integer.valueOf(decimalPart.charAt(i) + "");	//提取数字,左起
				result += big.charAt(num) + "" + units[1].charAt(i);	//数字变大写加上单位
			}
			result = result.replace("零角", "零");	//去掉"零角"的"角"
			result = result.replace("零分", "");	//去掉"零分"
		}else{
			result += "整";	//没有小数部分,则加上“整”
		}
		
		return result;
	}
	
	/**
	 * 处理整数部分的组,右起每四位是一组
	 * @param group 四位数字字符串
	 */
	public static String transformGroup(String group){
		String result = "";
		int length = group.length();
		for(int i=0; i < length; i++){
			int digit = Integer.valueOf(group.charAt(i)+"");	//单个数字,左起
			String unit = "";	//单位
			if(i!=length-1){
				unit = units[0].charAt(i) + "";	
			}
			result += big.charAt(digit) + unit; //数字变大写加上单位
		}
		
		result = result.replace("零仟", "零");
		result = result.replace("零佰", "零");
		result = result.replace("零拾", "零");
		
		while(result.contains("零零")){
			result = result.replace("零零", "零");	//如果有“零零”则变成一个“零”
		}
		
		if(!"零".equals(result) && result.endsWith("零")){
			result = result.substring(0, result.length()-1); //最未尾的可能出现的“零”去掉
		}
		return result;
	}


	/**
	 * @param args
	 */
	public static void main(String[] args) {
		double[] testData = {
			//测试数据一
			0,
			1,
			10,
			100,
			1000,
			10000,
			100000,
			1000000,
			10000000,
			100000000,
			1000000000,
			10000000000d,
			100000000000d,
			1000000000000d,
			10000000000000d,
			100000000000000d,
			//测试数据二
			110000000000000d,
			101000000000000d,
			100100000000000d,
			100010000000000d,
			100001000000000d,
			100000100000000d,
			100000010000000d,
			100000001000000d,
			100000000100000d,
			100000000010000d,
			100000000001000d,
			100000000000100d,
			100000000000010d,
			100000000000001d,
			//测试数据三
			101010101010101d,
			100100100100100d,
			100100010010001d,
			100100001000010d,
			100001000001000d,
			100010000100010d,
			111111111111111d,
			123456789012345d,
			//测试数据四(含小数)
			0.00,
			0.005,//0.01(转换成字符串后)
			0.015,//0.01
			0.025,//0.03
			0.035,//0.04
			0.045,//0.04
			0.055,//0.06
			1.384,
			10.125,
			100.02,
			1000.045,
			10000.055,
			100000.1,
			1000000.11,
			10000000.10,
			100000000.105,
			1000000000.010,
			//测试数据五(整数超过15位)
			1000000000000000d,
			1000000000000000.01d
		};
		
		for(double money : testData){
			String moneyStr = getDecimalStr(money);
			System.out.println( moneyStr + ":" + transform(moneyStr));
		}
	}
}

//打印结果:
/*
0:零圆整
1:壹圆整
10:壹拾圆整
100:壹佰圆整
1000:壹仟圆整
10000:壹万圆整
100000:壹拾万圆整
1000000:壹佰万圆整
10000000:壹仟万圆整
100000000:壹亿圆整
1000000000:壹拾亿圆整
10000000000:壹佰亿圆整
100000000000:壹仟亿圆整
1000000000000:壹万亿圆整
10000000000000:壹拾万亿圆整
100000000000000:壹佰万亿圆整
110000000000000:壹佰壹拾万亿圆整
101000000000000:壹佰零壹万亿圆整
100100000000000:壹佰万壹仟亿圆整
100010000000000:壹佰万零壹佰亿圆整
100001000000000:壹佰万零壹拾亿圆整
100000100000000:壹佰万零壹亿圆整
100000010000000:壹佰万亿壹仟万圆整
100000001000000:壹佰万亿零壹佰万圆整
100000000100000:壹佰万亿零壹拾万圆整
100000000010000:壹佰万亿零壹万圆整
100000000001000:壹佰万亿壹仟圆整
100000000000100:壹佰万亿零壹佰圆整
100000000000010:壹佰万亿零壹拾圆整
100000000000001:壹佰万亿零壹圆整
101010101010101:壹佰零壹万零壹佰零壹亿零壹佰零壹万零壹佰零壹圆整
100100100100100:壹佰万壹仟零壹亿零壹拾万零壹佰圆整
100100010010001:壹佰万壹仟亿壹仟零壹万零壹圆整
100100001000010:壹佰万壹仟亿零壹佰万零壹拾圆整
100001000001000:壹佰万零壹拾亿壹仟圆整
100010000100010:壹佰万零壹佰亿零壹拾万零壹拾圆整
111111111111111:壹佰壹拾壹万壹仟壹佰壹拾壹亿壹仟壹佰壹拾壹万壹仟壹佰壹拾壹圆整
123456789012345:壹佰贰拾叁万肆仟伍佰陆拾柒亿捌仟玖佰零壹万贰仟叁佰肆拾伍圆整
0:零圆整
0.01:零圆零壹分
0.01:零圆零壹分
0.03:零圆零叁分
0.04:零圆零肆分
0.04:零圆零肆分
0.06:零圆零陆分
1.38:壹圆叁角捌分
10.13:壹拾圆壹角叁分
100.02:壹佰圆零贰分
1000.04:壹仟圆零肆分
10000.06:壹万圆零陆分
100000.10:壹拾万圆壹角
1000000.11:壹佰万圆壹角壹分
10000000.10:壹仟万圆壹角
100000000.11:壹亿圆壹角壹分
1000000000.01:壹拾亿圆零壹分
1000000000000000:金额太大,不能处理整数部分超过15位的金额!
1000000000000000:金额太大,不能处理整数部分超过15位的金额!
*/ 

 

   个人觉得代码宜读、宜于维护才是最重要,转换大写这个小功能没有必要追求什么超高性能。

 

 

1
0
分享到:
评论

相关推荐

    人民币金额小写转换大写工具

    这个“人民币金额小写转换大写工具 1.0 绿色版”就是为了方便用户快速、准确地完成这一转换而设计的。绿色版意味着它是一个无需安装、直接运行的软件,不含有任何恶意插件,也不会在用户的计算机上留下任何痕迹,...

    BAT批处理脚本-格式转换-人民币金额小写转大写.cmd.zip

    本文将详细介绍"BAT批处理脚本-格式转换-人民币金额小写转大写.cmd.zip"这个压缩包中的知识点,以及如何利用批处理脚本来实现人民币金额的小写到大写的转换。 首先,我们要理解批处理脚本的基本概念。批处理脚本是...

    人民币金额小写转大写

    "人民币金额小写转大写"是一个常见的需求,它涉及到将阿拉伯数字(小写)转换成中文汉字(大写),以减少书写错误和欺诈的风险。在.NET框架下,C#语言提供了丰富的功能来处理这种转换。 首先,我们需要理解人民币...

    高到垓位低到毫的 人民币金额小写转大写

    可以实现高到垓位低到毫的 人民币金额小写转大写 C#完整的程序。

    人民币小写金额转大写金额(java版)

    ### 人民币小写金额转大写金额(Java版) #### 概述 本文将详细介绍一个Java程序,该程序用于将小写的人民币金额转换为大写形式。此转换主要用于财务、会计和其他正式场合,在这些场合中,大写金额是标准且必须的...

    在Excel中将人民币金额小写转成大写

    在Excel中将人民币金额小写转成大写 在Excel中将人民币金额小写转成大写 在Excel中将人民币金额小写转成大写

    c语言小程序(人民币小写金额转换成大写金额)

    首先,人民币金额的表示分为小写和大写两种形式。小写金额通常使用阿拉伯数字,如“1234.56元”,而大写金额则使用汉字,如“壹仟贰佰叁拾肆元伍角陆分”。转换过程中需要注意以下几点: 1. **数字到汉字的映射**:...

    C语言成序设计__实现人民币小写金额与大写金额的转换

    C语言实现人民币小写金额与大写金额的转换 C语言是一种广泛使用的编程语言,具有强大的功能和灵活性。本文中,我们将使用C语言实现人民币小写金额与大写金额的转换。 在中国,人民币的小写金额与大写金额的转换是...

    PHP 人民币小写转换成大写

    这篇博客"PHP 人民币小写转换成大写"提供了一个实用的解决方案,通过源码实现这一功能。 首先,我们需要理解人民币金额的大写规则。在中国,人民币金额的大写包括壹、贰、叁、肆、伍、陆、柒、捌、玖、零这些汉字,...

    小写人民币转大写ACCESS函数

    ### 小写人民币转大写ACCESS函数解析 #### 背景介绍 在日常的财务工作中,经常需要将数字格式的金额转换成汉字大写形式,尤其是在开具支票、填写电汇凭证或制作记账凭证时更为常见。这种转换不仅能够提高正式文件的...

    JS实现人民币小写转大写

    在JavaScript编程中,有时我们需要将人民币的数字金额(小写)转换为中文的大写形式,以便于财务报表或发票的规范书写。这个过程涉及到字符映射、数字处理以及字符串操作等多个知识点。以下是对这个主题的详细说明:...

    人民币小写金额转大写

    标题所提到的“人民币小写金额转大写”在SQL Server中的实现,主要依赖于自定义函数的编写。这段代码示例提供了一个名为`[dbo].[lowertoupper]`的存储过程,它接受一个`decimal(38,4)`类型的参数`@lowermoney`,并...

    财税实务:Excel中人民币小写金额转换大写的技巧.pdf

    财税实务:Excel中人民币小写金额转换大写的技巧 本篇文章将介绍在Excel中将人民币小写金额转换为大写金额的技巧。这种技巧主要应用于财税实务中,能够帮助用户快速将小写金额转换为大写金额。 1. 使用自定义格式...

    人民币小写金额转大写金额

    人民币小写金额转大写金额,不是简单的数字转换,而是在数字依次转换成大写文字后,再继续进行整理,将转换结果整理成符合大写金额书写要求的结果.

    java钱币小写转换大写

    这个工具类中的`toChineseCapital`方法可以接收一个小写金额字符串,返回转换后的人民币大写表示。在实际项目中,可能还需要对输入进行校验,确保其格式正确,例如检查是否包含非法字符,金额是否超出合理范围等。 ...

    小写人民币转换成大写人民币

    本文将详细介绍如何实现从小写(即阿拉伯数字)到大写(即汉字表示)的人民币金额转换,并通过一个具体的代码示例进行说明。 #### 一、转换规则概述 小写转大写的转换规则主要涉及以下几点: 1. **数字与汉字的...

Global site tag (gtag.js) - Google Analytics