using System;
namespace ExpertLib.ChineseSpecial
{
#region RMBException
/// <summary>
/// 人民幣轉換的錯誤
/// </summary>
public class RMBException : System.Exception
{
public RMBException(string msg)
: base(msg)
{
}
}
#endregion
/// <summary>
/// 實現將人民幣的數字形式轉換為中文格式,最大支援9兆兆。
/// </summary>
public static class RMB
{
#region 內部常量
private static string RMBUppercase = "零壹貳三肆伍陸柒捌玖";
private static string RMBUnitChar = "元拾佰仟萬拾佰仟億拾佰仟兆拾佰仟萬拾佰仟億拾佰仟兆"; //人民幣整數位對應的標誌
private const decimal MaxNumber =9999999999999999999999999.99m;
private const decimal MinNumber = -9999999999999999999999999.99m;
private static char[] cDelim = { '.' }; //小數分隔標識
#endregion
#region Convert
#region Convert <decimal>
/// <summary>
/// 轉換成人民幣大寫形式
/// </summary>
/// <param name="digital"></param>
/// <returns></returns>
public static string Convert(decimal number)
{
bool NegativeFlag=false;
decimal RMBNumber;
CheckNumberLimit(number);
RMBNumber = Math.Round(number, 2); //將四捨五入取2位小數
if (RMBNumber == 0)
{
return "零元整";
}
else if(RMBNumber < 0) //如果是負數
{
NegativeFlag = true;
RMBNumber = Math.Abs(RMBNumber); //取絕對值
}
else
{
NegativeFlag = false;
}
string buf = ""; // 存放返回結果
string strDecPart = ""; // 存放小數部分的處理結果
string strIntPart = ""; // 存放整數部分的處理結果
string[] tmp = null;
string strDigital = RMBNumber.ToString();
tmp = strDigital.Split(cDelim, 2); // 將資料分為整數和小數部分
if (RMBNumber >= 1m) // 大於1時才需要進行整數部分的轉換
{
strIntPart = ConvertInt(tmp[0]);
}
if (tmp.Length > 1) //分解出了小數
{
strDecPart = ConvertDecimal(tmp[1]);
}
else //沒有小數肯定是為整
{
strDecPart = "整";
}
if (NegativeFlag==false) //是否負數
{
buf = strIntPart + strDecPart;
}
else
{
buf = "負"+strIntPart + strDecPart;
}
return buf;
}
#endregion
#region Convert <double>
/// <summary>
/// 轉換成人民幣大寫形式
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
public static string Convert(double number)
{
decimal dec;
try
{
dec = System.Convert.ToDecimal(number);
}
catch
{
throw new RMBException("不能轉成標準的decimal類型:" + number.ToString());
}
return Convert(dec);
}
#endregion
#region Convert <float>
/// <summary>
/// 轉換成人民幣大寫形式
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
public static string Convert(float number)
{
decimal dec;
try
{
dec = System.Convert.ToDecimal(number);
}
catch
{
throw new RMBException("不能轉成標準的decimal類型:" + number.ToString());
}
return Convert(dec);
}
#endregion
#region Convert <int>
/// <summary>
/// 轉換成人民幣大寫形式
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
public static string Convert(int number)
{
decimal dec;
dec = System.Convert.ToDecimal(number);
return Convert(dec);
}
#endregion
#region Convert <long>
/// <summary>
/// 轉換成人民幣大寫形式
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
public static string Convert(long number)
{
decimal dec;
dec = System.Convert.ToDecimal(number);
return Convert(dec);
}
#endregion
#region Convert <string>
/// <summary>
/// 轉換成人民幣大寫形式
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
public static string Convert(string number)
{
decimal dec;
try
{
dec = System.Convert.ToDecimal(number,null);
}
catch
{
throw new RMBException("不能轉成標準的decimal類型:" + number);
}
return Convert(dec);
}
#endregion
#endregion
#region MaxSupportNumber
/// <summary>
/// 支援的最大轉換數
/// </summary>
public static decimal MaxSupportNumber
{
get
{
return MaxNumber;
}
}
#endregion
#region MinSupportNumber
/// <summary>
/// 支援的最小數
/// </summary>
public static decimal MinSupportNumber
{
get
{
return MinNumber;
}
}
#endregion
#region 內建函式
#region ConvertInt
private static string ConvertInt(string intPart)
{
string buf = "";
int length = intPart.Length;
int curUnit = length;
// 處理除個位以上的資料
string tmpValue = ""; // 記錄當前數值的中文形式
string tmpUnit = ""; // 記錄當前數值對應的中文單位
int i;
for (i = 0; i < length - 1; i++, curUnit--)
{
if (intPart[i] != '0')
{
tmpValue = DigToCC(intPart[i]);
tmpUnit = GetUnit(curUnit - 1);
}
else
{
// 如果當前的單位是"萬、億",則需要把它記錄下來
if ((curUnit - 1) % 4 == 0)
{
tmpValue = "";
tmpUnit = GetUnit(curUnit - 1);//
}
else
{
tmpUnit = "";
// 如果當前位是零,則需要判斷它的下一位是否為零,再確定是否記錄'零'
if (intPart[i + 1] != '0')
{
tmpValue = "零";
}
else
{
tmpValue = "";
}
}
}
buf += tmpValue + tmpUnit;
}
// 處理個位元據
if (intPart[i] != '0')
buf += DigToCC(intPart[i]);
buf += "元";
return CombinUnit(buf);
}
#endregion
#region ConvertDecimal
/// <summary>
/// 小數部分的處理
/// </summary>
/// <param name="decPart">需要處理的小數部分</param>
/// <returns></returns>
private static string ConvertDecimal(string decPart)
{
string buf = "";
int i = decPart.Length;
//如果小數點後均為零
if ((decPart == "0") || (decPart == "00"))
{
return "整";
}
if (decPart.Length > 1) //2位
{
if (decPart[0] == '0') //如果角位為零0.01
{
buf = DigToCC(decPart[1]) + "分"; //此時不可能分位為零
}
else if (decPart[1] == '0')
{
buf = DigToCC(decPart[0]) + "角整";
}
else
{
buf = DigToCC(decPart[0]) + "角";
buf += DigToCC(decPart[1]) + "分";
}
}
else //1位
{
buf += DigToCC(decPart[0]) + "角整";
}
return buf;
}
#endregion
#region GetUnit
/// <summary>
/// 擷取人民幣中文形式的對應位置的單位標誌
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
private static string GetUnit(int n)
{
return RMBUnitChar[n].ToString();
}
#endregion
#region DigToCC
/// <summary>
/// 數字轉換為相應的中文字元 ( Digital To Chinese Char )
/// </summary>
/// <param name="c">以字元形式儲存的數字</param>
/// <returns></returns>
private static string DigToCC(char c)
{
return RMBUppercase[c - '0'].ToString();
}
#endregion
#region CheckNumberLimit
private static void CheckNumberLimit(decimal number)
{
if ((number < MinNumber) || (number > MaxNumber))
{
throw new RMBException("超出可轉換的範圍");
}
}
#endregion
#region CombinUnit
/// <summary>
/// 合并兆億萬詞
/// </summary>
/// <param name="rmb"></param>
/// <returns></returns>
private static string CombinUnit(string rmb)
{
if (rmb.Contains("兆億萬"))
{
return rmb.Replace("兆億萬", "兆");
}
if (rmb.Contains("億萬"))
{
return rmb.Replace("億萬", "億");
}
if (rmb.Contains("兆億"))
{
return rmb.Replace("兆億", "兆");
}
return rmb;
}
#endregion
#endregion
}
}