中文数字表达式生成器

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
 }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值