المسارات
/
Julia
Julia
/
التمارين
/
تبادل العملات
تبادل العملات

تبادل العملات

تمرين تعلّمي

مقدمة

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

الأعداد الصحيحة

العدد الصحيح هو عدد "كامل" لا يحتوي على فاصلة عشرية.

في مفهوم الأساسيات، رأينا أنه يمكن إسناد قيمة عدد صحيح إلى متغير دون تحديد نوعه.

ولتحسين القراءة، يمكن استخدام الشرطات السفلية فاصلًا بين الأرقام. ويتجاهلها المُصرِّف.

julia> x = 3
3

julia> typeof(x)
Int64

julia> large_number = 1_234_567_890
1234567890

الأعداد العشرية

لن يفاجئك أن الأعداد العشرية تحتوي على فاصلة عشرية وجزء كسري بعدها.

julia> f = 3.45
3.45

julia> typeof(f)
Float64

وبالطبع، يُدعم الترميز العلمي.

julia> avogadro = 6.02e23
6.02e23

قد تفاجئك القيمتان العظمى والصغرى:

julia> typemax(Float64)
Inf

julia> typemin(Float64)
-Inf

اللانهاية قيمة صالحة!

العوامل الحسابية

كما ناقشنا في مفهوم الأساسيات، تعمل العوامل الحسابية في الغالب مثل الحساب المعتاد كما يُعلَّم للأطفال. لاحظ أن الرفع إلى قوة يستخدم ^، وليس ** (وكلاهما شائع في لغات أخرى).

2 + 3  # 5 (addition)
2 - 3  # -1 (subtraction)
2 * 3  # 6 (multiplication)
8 / 2  # 4.0 (division)
8 % 3  # 2 (remainder)
2 ^ 3  # 8 (exponentiation)

لكن هناك بعض التفاصيل الخاصة بـ Julia التي تستحق الحديث عنها.

الضرب

julia> x = 4.2
4.2

julia> 2 * x
8.4

julia> 2x
8.4

julia> 2.4x
10.08

قد يكون هذا مفاجئًا.

يمكنك دائمًا استخدام * كعامل إقحامي، كما في معظم لغات البرمجة الأخرى.

غير أن Julia صمّمها أشخاص يؤمنون بأن الكود ينبغي أن يشبه المعادلات الرياضية قدر الإمكان.

ولأن أسماء المتغيرات يجب أن تبدأ بحرف، فإن وضع رقم (صحيح أو عشري) قبل الاسم يُعالج كضرب ضمني.

على سبيل المثال، إذا أردنا مساحة سطح كرة، فبدلًا من 4 * pi * r * r يمكننا أن نفعل هذا:

julia> surface(r) = 4π * r^2
surface (generic function with 1 method)

julia> surface(3)
113.09733552923255

مع أن π ثابت مدمج، فهو أيضًا حرف (يوناني). لذلك لا يزال المحلِّل بحاجة إلى * صريح واحد للفصل بين π و r.

القسمة

استخدام / كعامل إقحامي يعطي دائمًا نتيجة عشرية، حتى مع مدخلات صحيحة.

أما القسمة الصحيحة، فلها خيارات أكثر.

julia> 10 / 3  # floating-point division
3.3333333333333335

julia> div(10, 3)  # integer division
3

julia> 10 ÷ 3  # synonym for div()
3

julia> 10 // 3  # rational number (fraction)
10//3

دالة div() مخصصة للقسمة الصحيحة، وتُقتطع نتيجتها نحو الصفر: إلى الأسفل مع الأعداد الموجبة، وإلى الأعلى مع الأعداد السالبة.

وكمرادف، يمكننا استخدام العامل الإقحامي ÷، مرة أخرى بهدف جعله يبدو أكثر رياضية. وإذا كنت تستخدم محررًا يدعم Julia، فأدخل \div ثم اضغط مفتاح <Tab>.

عامل // خارج نطاق هذا المفهوم. وفي الوقت الحالي، يمكننا القول فقط إن نتيجة // عدد "نسبي"، وهو ما يسميه معظم الناس كسرًا.

تحويل الأنواع العددية

غالبًا ما يحدث هذا تلقائيًا:

julia> x = 2 + 3.5
5.5

julia> typeof(x)
Float64

أضفنا Int64 إلى Float64، فحصلنا على نتيجة Float64.

في الواقع، حُوِّل العدد الصحيح بصمت إلى Float64 قبل إجراء الجمع.

إن التحويلات من عدد عشري إلى عدد صحيح لا بد أن تكون أكثر تعقيدًا. فماذا تريد أن تفعل بأي شيء يقع بعد الفاصلة العشرية؟

  • دالة round() تحوّل إلى أقرب عدد صحيح، وعند التعادل مثل 4.5 تُقرَّب إلى أقرب عدد صحيح زوجي.
  • floor() تُقرّب للأسفل، وceil() تُقرّب للأعلى، وtrunc() تُقرّب نحو الصفر.
  • محاولة التحويل مباشرة، على سبيل المثال باستخدام Int32()، ستفشل بخطأ InexactError.

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

julia> round(4.5)
4.0

julia> ceil(Int, 4.3)
5

ويمكن أيضًا التقريب إلى عدد محدد من الأرقام بعد الفاصلة العشرية باستخدام الكلمة المفتاحية digits.

julia> round(π, digits=10)
3.1415926536

القسمة على صفر

ألا يؤدي هذا ببساطة إلى خطأ؟ في الواقع، الأمر ليس بهذه البساطة.

القسمة الصحيحة باستخدام ÷ أو // ستؤدي إلى خطأ، كما قد تتوقع.

أما القسمة العشرية باستخدام / فتتبع نهجًا قد يُعتبر هندسيًا، لا نهج علوم الحاسوب المعتاد:

julia> 2 / 0
Inf

julia> 0 / 0
NaN

كما ناقشنا في قسم سابق، اللانهاية عدد عشري صالح في Julia، ويُمثَّل بـ Inf.

وعندما يكون البسط صفرًا أيضًا، تكون النتيجة غير معرّفة رياضيًا. حينها تتعامل معها Julia على أنها "ليست عددًا"، ويُمثَّل ذلك بـ NaN.

التعليمات

يخطط صديقك Chandler لزيارة بلدان بعيدة وغريبة في أنحاء العالم. ولسوء الحظ، مهارات Chandler في الرياضيات ليست جيدة. وهو قلق جدًا من أن يتعرض للاحتيال في محلات صرف العملات أثناء رحلته، ويريد منك أن تصنع له حاسبة عملات. وهذه هي مواصفاته للتطبيق:

1. تقدير القيمة بعد الصرف

أنشئ الدالة exchange_money()، وهي تأخذ معاملين اثنين:

  1. budget : المبلغ المالي الذي تخطط لصرفه.
  2. exchange_rate : مقدار العملة المحلية الذي يعادل وحدة واحدة من العملة الأجنبية.

يجب أن تُرجع هذه الدالة قيمة العملة بعد صرفها.

ملاحظة: إذا كانت عملتك هي الدولار الأمريكي وأردت صرف الدولار مقابل اليورو بسعر صرف قدره 1.20، فإن 1.20 USD == 1 EUR.

julia> exchange_money(127.5, 1.2)
106.25

2. حساب المبلغ المتبقي بعد الصرف

أنشئ الدالة get_change()، وهي تأخذ معاملين اثنين:

  1. budget : المبلغ المالي قبل الصرف.
  2. exchanging_value : المبلغ المالي الذي يُخصم من الميزانية ليتم صرفه.

يجب أن تُرجع هذه الدالة المبلغ المالي المتبقي من الميزانية.

julia> get_change(127.5, 120)
7.5

3. حساب قيمة الأوراق النقدية

أنشئ الدالة get_value_of_bills()، وهي تأخذ معاملين اثنين:

  1. denomination : قيمة الورقة النقدية الواحدة.
  2. number_of_bills : العدد الإجمالي للأوراق النقدية.

لا يتعامل كشك الصرف هذا إلا بنقود ذات مضاعفات محددة. يجب أن يكون المبلغ الإجمالي الذي تحصل عليه قابلًا للقسمة على قيمة «الورقة» الواحدة أو الوحدة، وقد يتبقى كسر أو باقٍ. يجب أن تُرجع دالتك قيمة الأوراق النقدية الإجمالية فقط (باستثناء الكسور) التي سيعيدها الكشك. ولسوء الحظ، يحتفظ الكشك بالباقي/الفكة لنفسه كمكافأة إضافية.

julia> get_value_of_bills(5, 128)
640

4. حساب عدد الأوراق النقدية

أنشئ الدالة get_number_of_bills()، وهي تأخذ amount وdenomination.

يجب أن تُرجع هذه الدالة عدد الأوراق النقدية التي يمكنك الحصول عليها ضمن المبلغ المعطى. بعبارة أخرى: كم عدد الأوراق النقدية الكاملة التي تدخل في المبلغ الابتدائي؟ تذكّر أنك لا تستطيع الحصول إلا على أوراق نقدية كاملة، لا على كسور منها، فاحرص على القسمة وفقًا لذلك. وبذلك فأنت تقرّب إلى الأسفل إلى أقرب ورقة/فئة نقدية كاملة.

julia> get_number_of_bills(127.5, 5)
25

5. حساب المتبقي بعد الصرف إلى أوراق نقدية

أنشئ الدالة get_leftover_of_bills()، وهي تأخذ amount وdenomination.

يجب أن تُرجع هذه الدالة المبلغ المتبقي الذي لا يمكن إعادته من المبلغ الابتدائي بالنظر إلى فئة الأوراق النقدية. ومن المهم جدًا معرفة المبلغ الذي يحتفظ به الكشك بدقة.

julia> get_leftover_of_bills(127.5, 20)
7.5

6. حساب القيمة بعد الصرف

أنشئ الدالة exchangeable_value()، وهي تأخذ budget وexchange_rate وspread وdenomination.

المعامل spread هو النسبة المئوية المخصومة كرسوم صرف، ويُكتب على هيئة عدد صحيح. ويجب تحويله إلى عدد عشري بقسمته على 100. إذا كان 1.00 EUR == 1.20 USD وكان spread يساوي 10، فسيصبح سعر الصرف الإجمالي في الواقع: 1.00 EUR == 1.32 USD، لأن 10% من 1.20 تساوي 0.12، وتُضاف هذه الرسوم الإضافية إلى الصرف.

يجب أن تُرجع هذه الدالة القيمة القصوى للعملة الجديدة بعد حساب سعر الصرف مضافًا إليه spread. تذكّر أن فئة العملة عدد صحيح، ولا يمكن تجزئتها.

ملاحظة: يجب أن تكون القيمة المُرجَعة من نوع عدد صحيح.

julia> exchangeable_value(127.25, 1.20, 10, 20)
80

julia> exchangeable_value(127.25, 1.20, 10, 5)
95
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Julia Exercism

مستعد لبدء تبادل العملات؟

سجّل في Exercism لتتعلّم وتتقن Julia عبر 35 مفهومًا128 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.