导读:
前些日,遇到这么个笔试题:
任选一种语言,写一段程序,将实数转成中文大学金额。如1234.12转成壹仟贰佰叁拾肆元壹角贰分。
大家觉得这题目是简单还难?是否有把握在一个小时内正确编码实现?我当时刚拿题目,觉得有几个难点。当场没实现完整。回到家好好用c#写了一遍,大家评说一下这代码实现如何?请多多请教。
转化的时候我遇到个郁闷,就是一兆等于多少亿,姑且按一兆等于亿亿来算吧,也就是百度的一个结果里说的“上法”:10^4=万, 10^8=亿,10^16=兆,10^32=京 。http://zhidao.baidu.com/question/19742157.html?si=1
我觉得难点有:(1)零的处理,例如不能出现两个或多个零相邻,万、亿位上的数字是零的话不一定没有万、亿字出现。(2)精度的处理。
总觉得现在的代码好像还是过于冗长,哪位仁兄能提供一个更简洁、运行效率更高的代码,不胜感激。不过要主意测试。
如果从代码风格、算法设计方面看,大家给这份代码一个怎样的评定呢?
1
using System; 2
using System.Collections.Generic; 3
using System.Text; 4
5
namespace CSharp大写金额 6
{ 7
/**
8
/// 将实数转化为中文大写金额 9
/// 作者:左轮 10
/// 时间:2007-11-4 11
///
12
public static class ConvertDoubleToChineseMoney 13
{ 14
/**
15
/// 数字和中文大写字符对应关系 16
///
17
private static Dictionary _numberChinese; 18
/**
19
/// 位数和位名(如个、拾、百等)对应关系 20
///
21
private static Dictionary _pointChineseNames; 22
/**
23
/// 最大位名对应的位数 24
///
25
private const int _maxPointNameIndex = 8
26
27
static ConvertDoubleToChineseMoney() 28
{ 29
_numberChinese = new Dictionary (10); 30
_numberChinese.Add(0, "零"); 31
_numberChinese.Add(1, "壹"); 32
_numberChinese.Add(2, "贰"); 33
_numberChinese.Add(3, "叁"); 34
_numberChinese.Add(4, "肆"); 35
_numberChinese.Add(5, "伍"); 36
_numberChinese.Add(6, "陆"); 37
_numberChinese.Add(7, "柒"); 38
_numberChinese.Add(8, "扒"); 39
_numberChinese.Add(9, "玖"); 40
41
_pointChineseNames = new Dictionary (8); 42
_pointChineseNames.Add(_maxPointNameIndex, "亿"); 43
_pointChineseNames.Add(4, "万"); 44
_pointChineseNames.Add(3, "仟"); 45
_pointChineseNames.Add(2, "佰"); 46
_pointChineseNames.Add(1, "拾"); 47
_pointChineseNames.Add(0, string.Empty); 48
_pointChineseNames.Add(-1, "角"); 49
_pointChineseNames.Add(-2, "分"); 50
}
51
52
/**
53
/// 将实数转化为中文大写金额 54
///
55
/// 用双精度浮点数表示的金额,不能大于9.0e+15,否则抛出ArgumentException异常
56
/// 中文大写金额字符串
57
public static string Convert(double money) 58
{ 59
if (money > 9.0e+15) 60
throw new ArgumentException("不能转换大于9.0e+15的数"); 61
62
if (money < 0.01) 63
return "零元"
64
65
//分开小数点左边和右边两部分分别转换,然后再合并
66
double rightPart = money % 1D; 67
double leftPart = money - rightPart; 68
69
string strLeftPart = ConvertLeftPart(leftPart); 70
string strRightPart = ConvertRightPart(rightPart); 71
72
StringBuilder sbChineseMoney = new StringBuilder(strLeftPart.Length + strRightPart.Length + 2); 73
if (string.IsNullOrEmpty(strLeftPart)) 74
{ 75
strRightPart = strRightPart.TrimStart('零'); 76
}
77
else
78
{ 79
sbChineseMoney.Append(strLeftPart); 80
sbChineseMoney.Append('元'); 81
}
82
sbChineseMoney.Append(strRightPart); 83
84
return sbChineseMoney.ToString(); 85
}
86
87
/**
88
/// 转换小数点左边部分 89
///
90
///
91
///
92
private static string ConvertLeftPart(double money) 93
{ 94
//中文大写金额,结果字符串
95
StringBuilder sbChineseMoney = new StringBuilder(_maxPointNameIndex * 2); 96
bool isBegin = false
97
//从左到右逐个将字翻译成中文大写金额
98
for (int numberIndex = _maxPointNameIndex * 2 - 1 numberIndex >= 0 numberIndex--) 99
{100
//获取一位上的数字
101
double number = GetNumbers(money, numberIndex, numberIndex);102
103
if (number > 0)104
isBegin = true
105
106
if (number == 0 && !isBegin)107
continue
108
//获取位名的key
109
int pointNameIndex = GetLeftPartPointNameIndex(numberIndex);110
//将当前数字的中文字符和位名插入结果字符串
111
if (number != 0)112
{113
//当前数字不为零,将数字和位名直接加入结果字符串尾部
114
sbChineseMoney.Append(_numberChinese[(int)number]);115
sbChineseMoney.Append(_pointChineseNames[pointNameIndex]);116
}
117
else
118
{119
//当前数字为零120
//如果结果字符串最后一个字符不是零,才将零加入结果字符串,避免多个相邻的零出现在结果字符串
121
if (sbChineseMoney[sbChineseMoney.Length - 1] != '零')122
sbChineseMoney.Append('零');123
//如果位名是个、拾、百、千,不出现在零后面124
//处理位名是万、亿的情况
125
if (pointNameIndex >= 4 && GetNumbers(money, numberIndex + pointNameIndex - 1, numberIndex) > 0D)126
sbChineseMoney = sbChineseMoney.Insert(sbChineseMoney.Length - 1, _pointChineseNames[pointNameIndex]);127
}
128
129
}
130
string strChineseMoney = sbChineseMoney.ToString();131
strChineseMoney = strChineseMoney.TrimEnd('零');132
return strChineseMoney;133
}
134
135
/**
136
/// 处理小数点右边部分137
///
138
///
139
///
140
private static string ConvertRightPart(double money)141
{142
if( money < 0.01 )143
return string.Empty;144
145
money *= 100
146
147
StringBuilder sbChineseMoney = new StringBuilder(4);148
149
int number = (int)GetNumbers(money, 1, 1);150
sbChineseMoney.Append(_numberChinese[number]);151
if (number != 0)152
sbChineseMoney.Append(_pointChineseNames[-1]);153
154
number = (int)GetNumbers(money, 0, 0);155
if (number != 0)156
{157
sbChineseMoney.Append(_numberChinese[number]);158
sbChineseMoney.Append(_pointChineseNames[-2]);159
}
160
161
return sbChineseMoney.ToString();162
}
163
/**
164
/// 获取指定位数范围的数字165
///
166
///
167
///
168
///
169
///
170
private static double GetNumbers(double money, int leftIndex, int rightIndex)171
{172
double pow1 = Math.Pow(10D, (double)(leftIndex + 1));173
double pow2 = Math.Pow(10D, (double)rightIndex);174
return (money % pow1 - money % pow2) / pow2;175
}
176
177
/**
178
/// 获取指定数字索引的位名在_pointChineseNames上的key179
///
180
///
181
///
182
/// 位名在_pointChineseNames上的key
183
private static int GetLeftPartPointNameIndex(int numberIndex)184
{185
int pointNameIndex = 0
186
int remainder = numberIndex % 4
187
if (remainder == 0)188
{189
if (numberIndex == 0)190
{191
pointNameIndex = 0
192
}
193
else
194
{195
for (int cast = _maxPointNameIndex; cast >= 4 cast /= 2)196
{197
if (numberIndex % cast == 0)198
{199
pointNameIndex = cast;200
break
201
}
202
}
203
}
204
}
205
else
206
{207
pointNameIndex = remainder;208
}
209
210
return pointNameIndex;211
}
212
}
213
}
测试结果截屏
posted on 2007-11-04 05:09 左轮阅读(2088) 评论(26) 编辑 收藏所属分类: 编程——.net
本文转自
http://www.cnblogs.com/zuolun/archive/2007/11/04/948654.html
前些日,遇到这么个笔试题:
任选一种语言,写一段程序,将实数转成中文大学金额。如1234.12转成壹仟贰佰叁拾肆元壹角贰分。
大家觉得这题目是简单还难?是否有把握在一个小时内正确编码实现?我当时刚拿题目,觉得有几个难点。当场没实现完整。回到家好好用c#写了一遍,大家评说一下这代码实现如何?请多多请教。
转化的时候我遇到个郁闷,就是一兆等于多少亿,姑且按一兆等于亿亿来算吧,也就是百度的一个结果里说的“上法”:10^4=万, 10^8=亿,10^16=兆,10^32=京 。http://zhidao.baidu.com/question/19742157.html?si=1
我觉得难点有:(1)零的处理,例如不能出现两个或多个零相邻,万、亿位上的数字是零的话不一定没有万、亿字出现。(2)精度的处理。
总觉得现在的代码好像还是过于冗长,哪位仁兄能提供一个更简洁、运行效率更高的代码,不胜感激。不过要主意测试。
如果从代码风格、算法设计方面看,大家给这份代码一个怎样的评定呢?
1
using System; 2
using System.Collections.Generic; 3
using System.Text; 4
5
namespace CSharp大写金额 6
{ 7
/**
8
/// 将实数转化为中文大写金额 9
/// 作者:左轮 10
/// 时间:2007-11-4 11
///
12
public static class ConvertDoubleToChineseMoney 13
{ 14
/**
15
/// 数字和中文大写字符对应关系 16
///
17
private static Dictionary _numberChinese; 18
/**
19
/// 位数和位名(如个、拾、百等)对应关系 20
///
21
private static Dictionary _pointChineseNames; 22
/**
23
/// 最大位名对应的位数 24
///
25
private const int _maxPointNameIndex = 8
26
27
static ConvertDoubleToChineseMoney() 28
{ 29
_numberChinese = new Dictionary (10); 30
_numberChinese.Add(0, "零"); 31
_numberChinese.Add(1, "壹"); 32
_numberChinese.Add(2, "贰"); 33
_numberChinese.Add(3, "叁"); 34
_numberChinese.Add(4, "肆"); 35
_numberChinese.Add(5, "伍"); 36
_numberChinese.Add(6, "陆"); 37
_numberChinese.Add(7, "柒"); 38
_numberChinese.Add(8, "扒"); 39
_numberChinese.Add(9, "玖"); 40
41
_pointChineseNames = new Dictionary (8); 42
_pointChineseNames.Add(_maxPointNameIndex, "亿"); 43
_pointChineseNames.Add(4, "万"); 44
_pointChineseNames.Add(3, "仟"); 45
_pointChineseNames.Add(2, "佰"); 46
_pointChineseNames.Add(1, "拾"); 47
_pointChineseNames.Add(0, string.Empty); 48
_pointChineseNames.Add(-1, "角"); 49
_pointChineseNames.Add(-2, "分"); 50
}
51
52
/**
53
/// 将实数转化为中文大写金额 54
///
55
/// 用双精度浮点数表示的金额,不能大于9.0e+15,否则抛出ArgumentException异常
56
/// 中文大写金额字符串
57
public static string Convert(double money) 58
{ 59
if (money > 9.0e+15) 60
throw new ArgumentException("不能转换大于9.0e+15的数"); 61
62
if (money < 0.01) 63
return "零元"
64
65
//分开小数点左边和右边两部分分别转换,然后再合并
66
double rightPart = money % 1D; 67
double leftPart = money - rightPart; 68
69
string strLeftPart = ConvertLeftPart(leftPart); 70
string strRightPart = ConvertRightPart(rightPart); 71
72
StringBuilder sbChineseMoney = new StringBuilder(strLeftPart.Length + strRightPart.Length + 2); 73
if (string.IsNullOrEmpty(strLeftPart)) 74
{ 75
strRightPart = strRightPart.TrimStart('零'); 76
}
77
else
78
{ 79
sbChineseMoney.Append(strLeftPart); 80
sbChineseMoney.Append('元'); 81
}
82
sbChineseMoney.Append(strRightPart); 83
84
return sbChineseMoney.ToString(); 85
}
86
87
/**
88
/// 转换小数点左边部分 89
///
90
///
91
///
92
private static string ConvertLeftPart(double money) 93
{ 94
//中文大写金额,结果字符串
95
StringBuilder sbChineseMoney = new StringBuilder(_maxPointNameIndex * 2); 96
bool isBegin = false
97
//从左到右逐个将字翻译成中文大写金额
98
for (int numberIndex = _maxPointNameIndex * 2 - 1 numberIndex >= 0 numberIndex--) 99
{100
//获取一位上的数字
101
double number = GetNumbers(money, numberIndex, numberIndex);102
103
if (number > 0)104
isBegin = true
105
106
if (number == 0 && !isBegin)107
continue
108
//获取位名的key
109
int pointNameIndex = GetLeftPartPointNameIndex(numberIndex);110
//将当前数字的中文字符和位名插入结果字符串
111
if (number != 0)112
{113
//当前数字不为零,将数字和位名直接加入结果字符串尾部
114
sbChineseMoney.Append(_numberChinese[(int)number]);115
sbChineseMoney.Append(_pointChineseNames[pointNameIndex]);116
}
117
else
118
{119
//当前数字为零120
//如果结果字符串最后一个字符不是零,才将零加入结果字符串,避免多个相邻的零出现在结果字符串
121
if (sbChineseMoney[sbChineseMoney.Length - 1] != '零')122
sbChineseMoney.Append('零');123
//如果位名是个、拾、百、千,不出现在零后面124
//处理位名是万、亿的情况
125
if (pointNameIndex >= 4 && GetNumbers(money, numberIndex + pointNameIndex - 1, numberIndex) > 0D)126
sbChineseMoney = sbChineseMoney.Insert(sbChineseMoney.Length - 1, _pointChineseNames[pointNameIndex]);127
}
128
129
}
130
string strChineseMoney = sbChineseMoney.ToString();131
strChineseMoney = strChineseMoney.TrimEnd('零');132
return strChineseMoney;133
}
134
135
/**
136
/// 处理小数点右边部分137
///
138
///
139
///
140
private static string ConvertRightPart(double money)141
{142
if( money < 0.01 )143
return string.Empty;144
145
money *= 100
146
147
StringBuilder sbChineseMoney = new StringBuilder(4);148
149
int number = (int)GetNumbers(money, 1, 1);150
sbChineseMoney.Append(_numberChinese[number]);151
if (number != 0)152
sbChineseMoney.Append(_pointChineseNames[-1]);153
154
number = (int)GetNumbers(money, 0, 0);155
if (number != 0)156
{157
sbChineseMoney.Append(_numberChinese[number]);158
sbChineseMoney.Append(_pointChineseNames[-2]);159
}
160
161
return sbChineseMoney.ToString();162
}
163
/**
164
/// 获取指定位数范围的数字165
///
166
///
167
///
168
///
169
///
170
private static double GetNumbers(double money, int leftIndex, int rightIndex)171
{172
double pow1 = Math.Pow(10D, (double)(leftIndex + 1));173
double pow2 = Math.Pow(10D, (double)rightIndex);174
return (money % pow1 - money % pow2) / pow2;175
}
176
177
/**
178
/// 获取指定数字索引的位名在_pointChineseNames上的key179
///
180
///
181
///
182
/// 位名在_pointChineseNames上的key
183
private static int GetLeftPartPointNameIndex(int numberIndex)184
{185
int pointNameIndex = 0
186
int remainder = numberIndex % 4
187
if (remainder == 0)188
{189
if (numberIndex == 0)190
{191
pointNameIndex = 0
192
}
193
else
194
{195
for (int cast = _maxPointNameIndex; cast >= 4 cast /= 2)196
{197
if (numberIndex % cast == 0)198
{199
pointNameIndex = cast;200
break
201
}
202
}
203
}
204
}
205
else
206
{207
pointNameIndex = remainder;208
}
209
210
return pointNameIndex;211
}
212
}
213
}
测试结果截屏
posted on 2007-11-04 05:09 左轮阅读(2088) 评论(26) 编辑 收藏所属分类: 编程——.net
本文转自
http://www.cnblogs.com/zuolun/archive/2007/11/04/948654.html