导读:
前些日,遇到这么个笔试题:
任选一种语言,写一段程序,将实数转成中文大学金额。如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