using System;
using System.Text;
using System.Collections;
namespace Math
{
/// <summary>
/// ChineseDigitConvertor 的摘要说明。
/// 已做详细测试!
/// </summary>
public class ChineseDigitConvertor
{
static string[] capitalDigits = new string[]{"零","一","二","三","四","五","六","七","八","九"};
static string[] capitalSamllUnits = new string[]{"十","百","千"};
static string[] chineseDigits = new string[]{"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
static string[] chineseSamllUnits = new string[]{"拾","百","千"};
static string[] chineseBigUnits = new string[]{"万","亿"};
static string[] chineseMoneyUnits = new string[]{"元","角","分"};
static string chinesePoint = "点";
private ChineseDigitConvertor()
{
}
public static string ToChineseNumberExpress(long val)
{
int boutNumber = 100000000;
Stack strStack = new Stack();
// 每八个数字为一轮转换。
// 首先应在循环后进行第一轮的转换。
// 若第一轮为零,则不压入栈中。
int temp = (int)(val % boutNumber);
string chineseStr = ConverEightDigit(temp);
if (chineseStr != chineseDigits[0])
{
strStack.Push(chineseStr);
}
// 准备按轮次(每八个数字为一轮转换)进行循环转换后面的数字
bool willHaveZero = temp < (boutNumber / 10);
val /= boutNumber;
while (val > 0)
{
temp = (int)(val % boutNumber);
chineseStr = ConverEightDigit(temp);
val = val / boutNumber;
// 若为“零”,直接跳过此轮循环
if (chineseStr == chineseDigits[0])
{
willHaveZero = temp < (boutNumber / 10);
continue;
}
// 检查上一轮八个数字所转换的数字中是否含有"千万"位,
// 以决定是否另行增加“零”字
// 例如:100000341 应读为“壹亿零叁百肆拾壹”,否则为“壹亿叁百肆拾壹”。
if (willHaveZero)
{
strStack.Push(chineseDigits[0]);
}
willHaveZero = temp < (boutNumber / 10);
strStack.Push(chineseBigUnits[1]);
strStack.Push(chineseStr);
}
return ConvertStack(strStack);
}
public static string ToChineseNumberExpress(double val)
{
StringBuilder strBuilder = new StringBuilder();
// 首先转换整数部分
strBuilder.Append(ToChineseNumberExpress((long)val));
double decVal = val % (double)1;
if (decVal > 0)
{
// 增加小数点
strBuilder.Append(chinesePoint);
}
while (decVal > 0)
{
decVal *= 10;
strBuilder.Append(chineseDigits[(int)decVal]);
decVal %= (double)1;
}
return strBuilder.ToString();
}
public static string ToChineseMoneyExpress(double val)
{
val = System.Math.Round(val, 2);
StringBuilder strBuilder = new StringBuilder();
// 首先转换整数部分
strBuilder.Append(ToChineseNumberExpress((long)val));
strBuilder.Append(chineseMoneyUnits[0]);
double decVal = val % (double)1;
// ?角
decVal *= 10;
strBuilder.Append(chineseDigits[(int)decVal]);
strBuilder.Append(chineseMoneyUnits[1]);
decVal %= (double)1;
// ?分
decVal *= 10;
strBuilder.Append(chineseDigits[(int)decVal]);
strBuilder.Append(chineseMoneyUnits[2]);
decVal %= (double)1;
return strBuilder.ToString();
}
public static string ToCapitalNumberExpress(long val)
{
string express = ToChineseNumberExpress(val);
return ReplaceChineseDigitWithCapitalDigit(express);
}
public static string ToCapitalNumberExpress(double val)
{
string express = ToChineseNumberExpress(val);
return ReplaceChineseDigitWithCapitalDigit(express);
}
public static string ToCapitalMoneyExpress(double val)
{
string express = ToChineseMoneyExpress(val);
return ReplaceChineseDigitWithCapitalDigit(express);
}
#region Private static methods.
static string ReplaceChineseDigitWithCapitalDigit(string express)
{
string ret = express;
for (int i = 1; i < chineseDigits.Length; i++)
{
ret = ret.Replace(chineseDigits[i], capitalDigits[i]);
}
// 替换“拾”为“十”
return ret.Replace(chineseSamllUnits[0], capitalSamllUnits[0]);
}
static string ConverEightDigit(int val)
{
int boutNumber = 10000;
System.Diagnostics.Debug.Assert(val < 100000000);
Stack strStack = new Stack();
// 每四个数字为一轮转换,一共有二轮。
// 首先进行第一轮的转换。
// 若第一轮为零,则不压入栈中。
string firstChineseStr = ConvertFourDigit((int)(val % boutNumber));
if (firstChineseStr != chineseDigits[0])
{
strStack.Push(firstChineseStr);
}
// 进行第二轮的转换
if (val >= boutNumber)
{
string secondChineseStr = ConvertFourDigit((int)(val / boutNumber % boutNumber));
// 检查上一轮四个数字所转换的数字中是否含有"千"位(在上一轮不为零的情况下),
// 以决定是否另行增加“零”字
// 例如:40341 应读为“肆万零叁百肆拾壹”,否则为“肆万叁百肆拾壹”。
int temp = (int)val % boutNumber;
if (temp < boutNumber / 10 && temp != 0)
{
strStack.Push(chineseDigits[0]);
}
strStack.Push(chineseBigUnits[0]);
strStack.Push(secondChineseStr);
}
return ConvertStack(strStack);
}
static string ConvertFourDigit(int val)
{
System.Diagnostics.Debug.Assert(val < 10000);
if (val == 0)
{
return chineseDigits[0];
}
Stack strStack = new Stack();
int temp = val;
int smallUnitIndex = -1;
while (temp > 0)
{
// 取未位数字
int digit = temp % 10;
temp /= 10;
if (digit == 0)
{
if (strStack.Count == 0 || (string)strStack.Peek() == chineseDigits[0])
{
smallUnitIndex++;
continue;
}
else
{
strStack.Push(chineseDigits[digit]);
smallUnitIndex++;
}
}
else
{
if (smallUnitIndex >= 0)
{
strStack.Push(chineseSamllUnits[smallUnitIndex]);
}
strStack.Push(chineseDigits[digit]);
smallUnitIndex++;
}
}
// 从栈中读出结果
return ConvertStack(strStack);
}
/// <summary>
/// 从栈中读出结果。
/// 若栈为空, 返回字符串“零”。
/// </summary>
static string ConvertStack(Stack stack)
{
if (stack.Count == 0)
{
return chineseDigits[0];
}
StringBuilder sb = new StringBuilder();
while (stack.Count > 0)
{
sb.Append((string)stack.Pop());
}
return sb.ToString();
}
#endregion
}
}