순수 수학적 방법을 기반으로 중국 화폐 디지털 변환 기능을 재귀적으로 구현한 C# 사례에 대한 자세한 소개

黄舟
풀어 주다: 2017-03-23 11:31:44
원래의
1922명이 탐색했습니다.

이 글에서는 주로 C#을 소개하며, 문자열 순회, 변환, 수학 연산과 관련된 C#의 연산 기술을 포함하여 순수 수학적 방법을 기반으로 중국 화폐 디지털 변환 기능을 재귀적으로 구현합니다. 다음

이 문서의 예에서는 순수 수학적 방법을 기반으로 C#에서 중국 통화 디지털 변환 함수를 재귀적으로 구현하는 방법을 설명합니다. 참고하시라고 자세한 내용은 다음과 같습니다.

최근 프로젝트 관계로 통화번호를 중국어로 변환하는 알고리즘을 작성해야 해서 처음으로 인터넷에서 검색해 봤습니다. 하나의 열을 제외하고 모두 (Replace) 대체 방법을 사용했기 때문에 저는 수학을 전공하기 때문에 다른 알고리즘을 작성하고 싶습니다. 이를 구현하기 위해 순수 수학을 사용합니다.

참고: 이 문서의 알고리즘은 1023(즉, 99990억) 미만의 통화 숫자 변환을 지원합니다.

화폐 중국어 설명: 코드를 설명하기 전에 먼저 화폐의 발음을 복습해보자.

10020002.23은 일천이백이위안 두 각 삼센트
1020은 일천이십위안으로 읽습니다.
100000 10만 위안으로 읽음
0.13 1다임 3센트로 읽음

코드:

테스트 엔지니어링

static void Main(string[] args)
{
Console.WriteLine("请输入金额");
string inputNum = Console.ReadLine();
while (inputNum != "exit")
{
//货币数字转化类
NumCast nc = new NumCast();
if (nc.IsValidated<string>(inputNum))
{
try
{
string chineseCharacter = nc.ConvertToChinese(inputNum);
Console.WriteLine(chineseCharacter);
}
catch (Exception er)
{
Console.WriteLine(er.Message);
}
}
else
{
Console.WriteLine("不合法的数字或格式");
}
Console.WriteLine("\n请输入金额");
inputNum = Console.ReadLine();
}
Console.ReadLine();
}
로그인 후 복사

화폐 변환 클래스(NumCast 클래스) 기능 소개

1. 상수 규정

/// <summary>
/// 数位
/// </summary>
public enum NumLevel { Cent, Chiao, Yuan, Ten, Hundred, Thousand, TenThousand, hundredMillon, Trillion };
/// <summary>
/// 数位的指数
/// </summary>
private int[] NumLevelExponent = new int[] { -2, -1, 0, 1, 2, 3, 4, 8, 12 };
/// <summary>
/// 数位的中文字符
/// </summary>
private string[] NumLeverChineseSign = new string[] { "分", "角", "元", "拾", "佰", "仟", "万", "亿", "兆" };
/// <summary>
/// 大写字符
/// </summary>
private string[] NumChineseCharacter = new string[] {"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
/// <summary>
/// 整(当没有 角分 时)
/// </summary>
private const string EndOfInt = "整";
로그인 후 복사

2. 정규식을 이용한 디지털 합법성 검증 확인

/// <summary>
/// 正则表达验证数字是否合法
/// </summary>
/// <param name="Num"></param>
/// <returns></returns>
public bool IsValidated<T>(T Num)
{
Regex reg = new Regex(@"^(([0])|([1-9]\d{0,23}))(\.\d{1,2})?$");
if (reg.IsMatch(Num.ToString()))
{
return true;
}
return false;
}
로그인 후 복사

3. 숫자 가져오기 예를 들어 1000은 NumLevel.Thousand

/// <summary>
/// 获取数字的数位使用log
/// </summary>
/// <param name="Num"></param>
/// <returns></returns>
private NumLevel GetNumLevel(double Num)
{
double numLevelLength;
NumLevel NLvl = new NumLevel();
if (Num > 0)
{
numLevelLength = Math.Floor(Math.Log10(Num));
for (int i = NumLevelExponent.Length - 1; i >= 0; i--)
{
if (numLevelLength >= NumLevelExponent[i])
{
NLvl = (NumLevel)i;
break;
}
}
}
else
{
NLvl = NumLevel.Yuan;
}
return NLvl;
}
로그인 후 복사

인지 확인합니다. 숫자 자리 사이에 점프가 있습니다. 즉, 한자 중간에 0을 추가해야 하는지 여부, 예를 들어 1020은 0으로 추가해야 하는지 여부입니다.

/// <summary>
/// 是否跳位
/// </summary>
/// <returns></returns>
private bool IsDumpLevel(double Num)
{
 if (Num > 0)
{
NumLevel? currentLevel = GetNumLevel(Num);
NumLevel? nextLevel = null;
int numExponent = this.NumLevelExponent[(int)currentLevel];
double postfixNun = Math.Round(Num % (Math.Pow(10, numExponent)),2);
if(postfixNun> 0)
nextLevel = GetNumLevel(postfixNun);
if (currentLevel != null && nextLevel != null)
{
if (currentLevel > nextLevel + 1)
{
return true;
}
}
}
return false;
}
로그인 후 복사

5. 긴 숫자를 두 개의 작은 숫자 배열으로 나눕니다. 예를 들어 9999억을 9999억과 0조로 나눕니다. 지원되지 않습니다.

/// <summary>
/// 是否大于兆,如果大于就把字符串分为两部分,
/// 一部分是兆以前的数字
/// 另一部分是兆以后的数字
/// </summary>
/// <param name="Num"></param>
/// <returns></returns>
private bool IsBigThanTillion(string Num)
{
bool isBig = false;
if (Num.IndexOf(&#39;.&#39;) != -1)
{
//如果大于兆
if (Num.IndexOf(&#39;.&#39;) > NumLevelExponent[(int)NumLevel.Trillion])
{
isBig = true;
}
}
else
{
//如果大于兆
if (Num.Length > NumLevelExponent[(int)NumLevel.Trillion])
{
isBig = true;
}
}
return isBig;
}
/// <summary>
/// 把数字字符串由‘兆&#39;分开两个
/// </summary>
/// <returns></returns>
private double[] SplitNum(string Num)
{
//兆的开始位
double[] TillionLevelNums = new double[2];
int trillionLevelLength;
if (Num.IndexOf(&#39;.&#39;) == -1)
trillionLevelLength = Num.Length - NumLevelExponent[(int)NumLevel.Trillion];
else
trillionLevelLength = Num.IndexOf(&#39;.&#39;) - NumLevelExponent[(int)NumLevel.Trillion];
//兆以上的数字
TillionLevelNums[0] = Convert.ToDouble(Num.Substring(0, trillionLevelLength));
//兆以下的数字
TillionLevelNums[1] = Convert.ToDouble(Num.Substring(trillionLevelLength ));
return TillionLevelNums;
}
로그인 후 복사

6. "壹十"으로 시작하는지 여부는 "十"으로 변경할 수 있습니다.

bool isStartOfTen = false;
while (Num >=10)
{
if (Num == 10)
{
isStartOfTen = true;
break;
}
//Num的数位
NumLevel currentLevel = GetNumLevel(Num);
int numExponent = this.NumLevelExponent[(int)currentLevel];
Num = Convert.ToInt32(Math.Floor(Num / Math.Pow(10, numExponent)));
if (currentLevel == NumLevel.Ten && Num == 1)
{
isStartOfTen = true;
break;
}
}
return isStartOfTen;
로그인 후 복사

7. 조련보다 배열에서 변환된 통화 문자열

/// <summary>
/// 合并分开的数组中文货币字符
/// </summary>
/// <param name="tillionNums"></param>
/// <returns></returns>
private string ContactNumChinese(double[] tillionNums)
{
string uptillionStr = CalculateChineseSign(tillionNums[0], NumLevel.Trillion, true, IsStartOfTen(tillionNums[0]));
string downtrillionStr = CalculateChineseSign(tillionNums[1], null, true,false);
string chineseCharactor = string.Empty;
//分开后的字符是否有跳位
if (GetNumLevel(tillionNums[1] * 10) == NumLevel.Trillion)
{
chineseCharactor = uptillionStr + NumLeverChineseSign[(int)NumLevel.Trillion] + downtrillionStr;
}
else
{
chineseCharactor = uptillionStr + NumLeverChineseSign[(int)NumLevel.Trillion];
if (downtrillionStr != "零元整")
{
chineseCharactor += NumChineseCharacter[0] + downtrillionStr;
}
else
{
chineseCharactor += "元整";
}
}
return chineseCharactor;
}
로그인 후 복사

8. 중국 통화 번호를 재귀적으로 계산

/// <summary>
/// 计算中文字符串
/// </summary>
/// <param name="Num">数字</param>
/// <param name="NL">数位级别 比如1000万的 数位级别为万</param>
/// <param name="IsExceptTen">是否以‘壹拾&#39;开头</param>
/// <returns>中文大写</returns>
public string CalculateChineseSign(double Num, NumLevel? NL ,bool IsDump,bool IsExceptTen)
{
Num = Math.Round(Num, 2);
bool isDump = false;
//Num的数位
NumLevel? currentLevel = GetNumLevel(Num);
int numExponent = this.NumLevelExponent[(int)currentLevel];
string Result = string.Empty;
//整除后的结果
int prefixNum;
//余数 当为小数的时候 分子分母各乘100
double postfixNun ;
if (Num >= 1)
{
prefixNum = Convert.ToInt32(Math.Floor(Num / Math.Pow(10, numExponent)));
postfixNun = Math.Round(Num % (Math.Pow(10, numExponent)), 2);
}
else
{
prefixNum = Convert.ToInt32(Math.Floor(Num*100 / Math.Pow(10, numExponent+2)));
postfixNun = Math.Round(Num * 100 % (Math.Pow(10, numExponent + 2)), 2);
postfixNun *= 0.01;
}
if (prefixNum < 10 )
{
//避免以‘壹拾&#39;开头
if (!(NumChineseCharacter[(int)prefixNum] == NumChineseCharacter[1]
&& currentLevel == NumLevel.Ten && IsExceptTen))
{
Result += NumChineseCharacter[(int)prefixNum];
}
else
{
IsExceptTen = false;
}
//加上单位
if (currentLevel == NumLevel.Yuan )
{
////当为 “元” 位不为零时 加“元”。
if (NL == null)
{
Result += NumLeverChineseSign[(int)currentLevel];
//当小数点后为零时 加 "整"
if (postfixNun == 0)
{
Result += EndOfInt;
}
}
}
else
{
Result += NumLeverChineseSign[(int)currentLevel];
}
 //当真正的个位为零时加上“元”
if (NL == null && postfixNun < 1 && currentLevel > NumLevel.Yuan && postfixNun > 0)
{
Result += NumLeverChineseSign[(int)NumLevel.Yuan];
}
}
else
{
//当 前缀数字未被除尽时, 递归下去
NumLevel? NextNL = null;
if ((int)currentLevel >= (int)(NumLevel.TenThousand))
NextNL = currentLevel;
Result += CalculateChineseSign((double)prefixNum, NextNL, isDump, IsExceptTen);
if ((int)currentLevel >= (int)(NumLevel.TenThousand))
{
Result += NumLeverChineseSign[(int)currentLevel];
}
}
//是否跳位
// 判断是否加零, 比如302 就要给三百 后面加零,变为 三百零二。
if (IsDumpLevel(Num))
{
Result += NumChineseCharacter[0];
isDump = true;
}
//余数是否需要递归
if (postfixNun > 0)
{
Result += CalculateChineseSign(postfixNun, NL, isDump, false);
}
else if (postfixNun == 0 && currentLevel > NumLevel.Yuan )
{
//当数字是以零元结尾的加上 元整 比如1000000一百万元整
if (NL == null)
{
Result += NumLeverChineseSign[(int)NumLevel.Yuan];
Result += EndOfInt;
}
}
return Result;
}
로그인 후 복사

9. 전화.

/// <summary>
/// 外部调用的转换方法
/// </summary>
/// <param name="Num"></param>
/// <returns></returns>
public string ConvertToChinese(string Num)
{
if (!IsValidated<string>(Num))
{
throw new OverflowException("数值格式不正确,请输入小于9999亿兆的数字且最多精确的分的金额!");
}
string chineseCharactor = string.Empty;
if (IsBigThanTillion(Num))
{
double[] tillionNums = SplitNum(Num);
chineseCharactor = ContactNumChinese(tillionNums);
}
else
{
double dNum = Convert.ToDouble(Num);
chineseCharactor = CalculateChineseSign(dNum, null, true, IsStartOfTen(dNum));
}
return chineseCharactor;
}
로그인 후 복사

요약:

저는 개인적으로 프로그램의 영혼은 시스템의 비즈니스 로직만큼 클 수 있는 알고리즘이라고 생각합니다. 통화 숫자를 중국어로 변환하는 알고리즘만큼 작은 논리적 사고가 모든 곳에 반영됩니다.

요구사항을 좋은 수학적 모델로 추상화할 수 있는지 여부는 프로그램 구현의 복잡성과 안정성과 직접적인 관련이 있습니다. 일반적으로 사용되는 일부 기능에서 다양한 알고리즘을 생각하는 것은 아이디어를 개발하는 데 매우 도움이 됩니다.

위 내용은 순수 수학적 방법을 기반으로 중국 화폐 디지털 변환 기능을 재귀적으로 구현한 C# 사례에 대한 자세한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!