65.9K
CodeProject 正在变化。 阅读更多。
Home

数字转单词(阿拉伯语版本)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (42投票s)

2010 年 9 月 27 日

CPOL

4分钟阅读

viewsIcon

244825

downloadIcon

10803

本文介绍了如何将数字转换为英语和阿拉伯语的文字。

简介  

在本文中,我将讨论将数字转换为英语和阿拉伯语的文字(阿拉伯语发音为 Tafqeet)。

背景

我当时正在编程我的项目,需要一个将数字转换为书面文本的代码。

我们的项目是多语言的,所以我需要两个版本:一个用于英语,一个用于阿拉伯语。

我搜索了“Number to Text”或“Number to Word”,找到了很多用于将数字转换为英语书面文本的代码,其中许多代码运行良好。

我还找到了将数字转换为阿拉伯语文本的代码,但不幸的是,其中许多代码未能如预期那样工作!

因此,我决定走一条漫长的道路来构建一个类来完成阿拉伯语的转换,并且还添加了英语语言支持。

这是一个使用该类的测试项目的屏幕截图

Tafqeet2.jpg

Using the Code

我必须提到,我使用了 Justin Rogers 在此链接中编写的代码作为起点:http://weblogs.asp.net/justin_rogers/articles/151757.aspx

本文包含将小数转换为其等效英语单词的良好代码,但我应用程序中的数字实际上是货币金额,所以我需要添加货币名称(我们的项目也是多国货币,所以我不得不从国家货币中动态构建字符串)。

在对 Justin 的代码进行一些小的更改以满足我的英语数字转文字需求后,这是最简单的部分。

现在是复杂的部分:将数字转换为阿拉伯语的文字!

阿拉伯语非常复杂,当涉及到将其转换为单词时,我认为它是最难的语言,因为它有很多规则,这些规则取决于“数字”的状态和“被数”的状态。

例如

数字一和二在阴性状态下与被数相匹配,而数字三到十则与被数相反,等等。

因此,我使用了一种方法来确定数字的阴性状态,该方法使用其组级别和货币名称的阴性字段状态。这是该方法

private string GetDigitFeminineStatus(int digit, int groupLevel)
{
    if (groupLevel == -1)
    { // if it is in the decimal part
        if (Currency.IsCurrencyPartNameFeminine)
            return arabicFeminineOnes[digit]; // use feminine field
        else
            return arabicOnes[digit];
    }
    else
        if (groupLevel == 0)
        { 
            if (Currency.IsCurrencyNameFeminine)
                return arabicFeminineOnes[digit];// use feminine field
            else
                return arabicOnes[digit];
        }
        else
            return arabicOnes[digit];
}

整个转换过程取决于将数字划分为组级别。每个组包含 3 位数字,这些级别按此示例编号

Number: 987,654,321.345
345: Group Level -1
321: Group Level 0 
654: Group Level 1
987: Group Level 2 

这是通过此代码实现的

Byte group = 0;
while (tempNumber >= 1)
{
    // separate number into groups
    int numberToProcess = (int)(tempNumber % 1000);
    
    tempNumber = tempNumber / 1000;
    
    // convert group into its text
    string groupDescription = ProcessArabicGroup
    (numberToProcess, group, Math.Floor(tempNumber));
    
    group++;
}

然后我们必须处理每个组并根据其组级别将其转换为文本。

在 `ProcesArabicGroup` 方法内部,我们检查 `200` 的特殊情况,因为它在阿拉伯语中有其特殊的规则

if (hundreds > 0)
{
     if (tens == 0 && hundreds == 2) // ???? ??????
         retVal = String.Format("{0}", arabicAppendedTwos[0]);
     else //  ?????? ???????
         retVal = String.Format("{0}", arabicHundreds[hundreds]);
} 

数字 2 也有另一个特殊规则,由此代码讨论

if (tens == 2 && hundreds == 0 && groupLevel > 0)
{ // This is special case for number 2 when it comes alone in the group
    if (_intergerValue == 2000 || _intergerValue == 2000000 || 
    _intergerValue == 2000000000 || _intergerValue == 2000000000000 || 
    _intergerValue == 2000000000000000 || _intergerValue == 2000000000000000000)
        retVal = String.Format("{0}", arabicAppendedTwos[groupLevel]); // ?? ???? ???????
    else
        retVal = String.Format("{0}", arabicTwos[groupLevel]);//  ?? ???? ???????
}

对于大于 20 的组数字,它被视为由 2 位数字组成,因此每个数字都会获得其自己的转换文本。

int ones = tens % 10;
tens = (tens / 10) - 2; // 20's offset
 
if (ones > 0)
{
    if (retVal != String.Empty)
        retVal += " ? ";
 
    // Get Feminine status for this digit
    retVal += GetDigitFeminineStatus(ones, groupLevel);
}
 
if (retVal != String.Empty)
    retVal += " ? ";
 
// Get Tens text
retVal += arabicTens[tens];

此外,阿拉伯语对货币名称很敏感,这取决于数字的状态,因此我不得不为同一个货币名称添加四个不同的名称以支持所有状态。当构建最终的 `String` 时,它们的字段会在方法末尾使用

if (_intergerValue != 0)
{ // here we add currency name depending on _intergerValue : 1 ,2 , 3--->10 , 11--->99
    int remaining100 = (int)(_intergerValue % 100);
    
    if (remaining100 == 0)
        formattedNumber += Currency.Arabic1CurrencyName;
    else
        if (remaining100 == 1)
            formattedNumber += Currency.Arabic1CurrencyName;
        else
            if (remaining100 == 2)
            {
                if (_intergerValue == 2)
                    formattedNumber += Currency.Arabic2CurrencyName;
                else
                    formattedNumber += Currency.Arabic1CurrencyName;
            }
            else
                if (remaining100 >= 3 && remaining100 <= 10)
                    formattedNumber += Currency.Arabic310CurrencyName;
                else
                    if (remaining100 >= 11 && remaining100 <= 99)
                        formattedNumber += Currency.Arabic1199CurrencyName;

我创建了一个类来简化这个过程,它叫做 `CurrencyInfo`,它包含了 `Currency` 对象的定义。它具有以下属性

CurrencyID = 0;

仅 ID

CurrencyCode = "SYP";

其代码

IsCurrencyNameFeminine = true;

货币名称是阴性还是非阴性?

EnglishCurrencyName = "Syrian Pound";

例如:one Syrian Pound

EnglishPluralCurrencyName = "Syrian Pounds";

例如:thirty four Syrian Pounds

EnglishCurrencyPartName = "Piaster";

用于小数部分

EnglishPluralCurrencyPartName = "Piasteres";

用于小数部分

Arabic1CurrencyName = "ليرة سورية";

阿拉伯语数字一

Arabic2CurrencyName = "ليرتان سوريتان";

阿拉伯语数字二

Arabic310CurrencyName = "ليرات سورية";

阿拉伯语数字三到十

Arabic1199CurrencyName = "ليرة سورية";

阿拉伯语数字十一以上

Arabic1CurrencyPartName = "قرش";

阿拉伯语小数部分

Arabic2CurrencyPartName = "قرشان";

阿拉伯语小数部分

Arabic310CurrencyPartName = "قروش";

阿拉伯语小数部分

Arabic1199CurrencyPartName = "قرش";

阿拉伯语小数部分

PartPrecision = 2;

部分精度,例如:1 叙利亚镑 = 100 皮阿斯特(2 是零的数量)

IsCurrencyPartNameFeminine

货币部分名称是阴性还是非阴性?

从表中可以看出,通过填写指定的字段,设置任何其他货币都非常容易。

关注点

希望这对您有所帮助。

请随时对代码进行更正/建议任何修改。

历史

  • 2010 年 9 月 27 日:初次发帖
  • 2011 年 4 月 9 日:修复了解决方案中的一个小问题(一位会员指出)
  • 2011 年 5 月 5 日:为本文添加了 VB.NET 等效代码
  • 2012 年 2 月 17 日:修复了代码中的一个小错误
© . All rights reserved.