الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

تفقيط الأرقام باللغة العربية

رائج
بدأه Adel Khayata في 28 سبتمبر 2010 · 12 رد · 27,817 مشاهدة · في Microsoft Visual C#.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم.

أثناء عملي على مشروع كبير في الشركة لزمني عملية تحويل الأرقام إلى نص و التي تسمى في اللغة العربية ( التفقيط ) و أثناء بحثي على الانترنيت على كود جاهز لهذه العملية, وجدت بعضاً منها و لكن أغليها لم يكن بالجودة الكافية لذلك قررت العمل عليها بشكل كامل بحيث تغطي كافة الاحتمالات و أحببت مشاركتكم بالكود لتعم الفائدة و أيضاً لتقبل الملاحظات و الاقتراحات.

أولاً هذه صورة عن مشروع تجريبي يبين عمل الكلاس:

post-236-013105600 1285691966_thumb.jpg

وهذا لينك المشروع التجريبي: NumberToWord.zip

سأحاول أن أقوم بشرح الكلاس بشكل مبسط.

عندما نقرأ أي رقم باللغة العربية فإننا نقسمه إلى مجموعات: المئات , الآلاف , الملايين , المليارات ... الخ , فالعملية ببساطة تقوم على تقسيم العدد إلى مجموعات مكونة من 3 خانات.

فمثلاً: الرقم: 987,654,321.123 يتم تقسيمه إلى المجموعات التالية:

123: المجموعة -1

321: المجموعة 0

654: المجموعة 1

987: المجموعة 2

و هذا الكود الذي يقوم بذلك:

            Byte group = 0;
            while (tempNumber >= 1)
            {
                // seperate 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++;
            }

الآن يتم تحويل النص لكل مجموعة على حسب مستواها عن طريق التابع: ProcessArabicGroup و من ثم يتم جمع النصوص مع بعضها لتكوين النص الكامل.

اللغة العربية فيها نظام معقد لتفقيط الأرقام, فهناك حالات مختلفة للأرقام فمثلاً الرقم واحد و اثنان يوافقان المعدود في التذكير و التأنيث في حين أن الأرقام من 3 إلى 10 تخالفان المعدود ... الخ. (شرح قواعد الأعداد في اللغة العربية خارج نطاق هذه المقالة).

الآن: ضمن التابع ProcessArabicGroup يتم معالجة المجموعة المكونة من 3 خانات على حسب قواعد اللغة العربية و يتم ذلك عن طريق أوامر :if/else و هناك قواعد عامة و استثناءات لهذه القواعد.

فمثلاً الرقم 200125 يقرأ مئتا ألف و مائة و خمس و عشرون ( لاحظ تم استخدام مئتا عوضاً عن مئتان و هي حالة المضاف ) و هذا هو الكود:

             if (hundreds > 0)
            {
                if (tens == 0 && hundreds == 2) // حالة المضاف
                    retVal = String.Format("{0}", arabicAppendedTwos[0]);
                else //  الحالة العادية
                    retVal = String.Format("{0}", arabicHundreds[hundreds]);
          }

و كما ستلاحظون عن مراجعة كود الكلاس فستجدون أن معظمه هو أوامر: if/else لتحديد الحالات الاستثنائية.

من الأمور المهمة في الكود أنه يعالج الأرقام في حالة كان المعدود مذكراً أو مؤنثاً و هنا أنا أستخدم العملة كمعدود ( هذه كانت متطلبات مشروع شركتي) و قد واجهتني مشكلة أن برنمجي متعدد الدول, أي أنني أحتاج أن أظهر التفقيط بعدة عملات ( ليرة سورية, درهم إماراتي , ريال سعودي ... ) و أيضاً الكلاس يعالج الأرقام التي بعد الفاصلة و أيضاً يوجد معدود مختلف لها ( قرش , فلس , هللة ....).

يوجد تابع يعالج هذه الحالة و هو GetDigitFeminineStatus وهو يعتمد على مستوى المجموعة و هذا هو الكود:

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

و لتسهيل العملية قمت بإنشاء كلاس للعملة اسمه CurrencyInfo و هذا هو تفصيله:

post-236-023035700 1285691955_thumb.jpg

و بعد تحويل الأرقام إلى نص يتم إضافة اسم العملة و أجزاؤها على حسب قواعد اللغة العربية و أيضاً باستخدام أوامر: if/else كما في الكود التالي:

             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;

أرجو أن أكون قد أوضحت النقاط الرئيسية التي يرتكز عليها الكود و أنا أرحب بملاحظاتكم و تعديلاتكم على الكود.

لا تنسونا من دعواتكم.

المرفقات
Tafqeet.jpgTafqeet2.jpg
7
#2

جزاك الله خير

كان لدي فكرة أن أقوم بعملها ، ولكن أديت الواجب ... :)

لدي اقتراح ....

أن تجعل اسم العملة (ليرة سورية ، قرش) يتم إدخالها من قبل المستخدم ، حتى تعم الفائدة لجميع المبرمجين العرب

ولك تحياتي أخي

#3

أخي: أنا صممت هذا البرنامج فقط لتجربة الكلاس NumberToWord و الكود يحتوي على كلاس مساعد اسمه CurrencyInfo يستطيع المبرمج أن يستفيد منه من أجل أن يقوم بإدخال معلومات العملة المطلوبة.

فمثلاً: في برنامجي و كوني أستخدم عملات مختلفة فيه ( بحدود 30 عملة ) فقد قمت بإنشاء جدول خاص في قاعدة البيانات يحتوي على كل تفاصيل العملات المطلوبة : ( هي نفس الكلاس CurrencyInfo ) و فقط علي تمرير كلاس العملة المطلوبة حتى أحصل على النص مفقطاً بهذه العملة.

1
#4

يوجد مكتبة جاهزة من مايكروسوفت تقوم بالتفقيط واعتقد يمكن الاستفادة او البناء فوقها للوصول الى المطلوب .

Microsoft Visual Studio International Feature Pack 2.0

#5

شكراً أخي طارق على الملاحظة.

الغريب أنني لم ألحظ هذا البرنامج أثناء بحثي على النت على كود يقوم بهذه العملية!!

على كل قمت بتنزيل هذا البرنامج و جربته و يبدو أنه يقوم فعلاً بتفقيط الأرقام إلى اللغة العربية و لكن بدون أن يأخذ بعين الاعتبار حالات التنوين و الإضافة مما يجعل النص ركيكاً نوعاً ما.

كما أن ميزة إضافة اسم العملة إلى النص لا تعمل مع اللغة العربية!!

#6

السلام عليكم

اقتباس
على كل قمت بتنزيل هذا البرنامج و جربته و يبدو أنه يقوم فعلاً بتفقيط الأرقام إلى اللغة العربية و لكن بدون أن يأخذ بعين الاعتبار حالات التنوين و الإضافة مما يجعل النص ركيكاً نوعاً ما.

فقط اردت التنويه الى هذه المكتبة لكن لم اجربها ولم ادقق بها وارجو ان يكون عملك افضل منها .

#7

Adel Khayata جزاك الله خير ورفع قدرك وعز شئنك ورحمك ووالديك

نفعني جداً ..

=========

كود تحويل الارقام الى حروف بالغة السي شارب C#.net

C#

تم تعديل هذه المشاركة بواسطة عبد الله ساعاتي في 6 أكتوبر 2010 في 19:39

#8

أللللللللللللللللللف شكر اخي عادل عالكود الرااااااااااااااائع... بصراحة وفرت علي كتير وقت لكتابة هالكود

جزاك الله كل خير وجعلها في ميزان حسناتك

1

--==iceDragon==--
ماجستير نظم دعم القرار الذكية IDSS

#9

جزاك الله خيرا اخي الكريم وزادك الله علما ونفعك بما تعلم إن شاء الله

شكرا جزيلا على الكود وعلى الدالة

1
#10

بارك الله فيك اخي الكريم على المقالة الرائعة

ان شاء الله في ميزان حسناتك

واتمى لك كل التوفيق

1
#11

ممتاز يا عادل

لقد قمت بتعديل الكود بإضافة الجنية المصري

 

هذا هو التعديل على CurrencyInfo.cs

case Currencies.EGP:
   CurrencyID = 5;
   CurrencyCode = "EGP";
   IsCurrencyNameFeminine = false;
   EnglishCurrencyName = "Egyptian Pound";
   EnglishPluralCurrencyName = "Egyptian Pounds";
   EnglishCurrencyPartName = "Piaster";
   EnglishPluralCurrencyPartName = "Piasters";
   Arabic1CurrencyName = "جنيه مصري";
   Arabic2CurrencyName = "جنيهان مصريان";
   Arabic310CurrencyName = "جنيهات مصرية";
   Arabic1199CurrencyName = "جنيها مصريا";
   Arabic1CurrencyPartName = "قرش";
   Arabic2CurrencyPartName = "قرشان";
   Arabic310CurrencyPartName = "قروش";
   Arabic1199CurrencyPartName = "قرشا";
   PartPrecision = 2;
   IsCurrencyPartNameFeminine = false;
   break;

تم تعديل هذه المشاركة بواسطة رامي رفيق في 30 سبتمبر 2013 في 17:01

2
#12

أشكرك كل الشكر يا أستاذ عادل وجعله الله في ميزان حسناتك :yes_80_anim_gif:

#13

الرجاء الإجابة عن هذا السؤال الموجود في هذا الرابط أدناه أو المشاركة برأي:

http://goo.gl/H7Q1zu

شكراً للجميع

مواضيع مشابهة