Complex numbers ليست معقدة.
إنها تحتاج فقط إلى اسم أقل إثارة للقلق.
إنها مفيدة جدًا، خصوصًا في الهندسة والعلوم، حتى إن R يضم الأعداد المركبة ضمن الأنواع الذرية القياسية إلى جانب integer وdouble وlogical وcharacter وraw.
العدد complex في R قيمة واحدة.
لكن عند الاستخدام يمكن اعتباره زوجًا من الأعداد.
يُسمّى هذان الجزآن الجزء «الحقيقي» والجزء «التخيلي»، لأسباب تاريخية مؤسفة.
ومرة أخرى، الأفضل أن نركّز على البساطة الكامنة وراءه لا على أسمائه الغريبة.
لإنشاء عدد مركب من عددين حقيقيين، أضف اللاحقة i إلى الجزء التخيلي.
2+3i
#> [1] 2+3i
typeof(2+3i)
#> [1] "complex"
أما لإنشاء عدد مركب من متغيرات حقيقية، فلن تنجح الصيغة السابقة.
فكتابة r + imi تجعل المحلّل يظن أن imi اسم متغير (غير موجود).
إما أن تضرب الجزء التخيلي في 1i أو أن تستخدم الدالة [complex()][ref-complex]:
r <- 2
im <- 3
r + im * 1i
#> [1] 2+3i
# must include the `real` and `imaginary` keywords
complex(real = r, imaginary = im)
#> [1] 2+3i
قد تتساءل: لماذا i وليس j؟
يفضّل معظم المهندسين j.
ويفضّل معظم العلماء والرياضيين الرمز الرياضي i للدلالة على التخيلي، لكن هذا الرمز يتعارض مع استخدام i بمعنى التيار في الهندسة الكهربائية.
اختار R الحرف i، واختارت Python الحرف j، وتجنّبت Julia هذا الخلاف باختيار im.
فكن حذرًا عند التنقل بين لغات البرمجة في مجالات [العلوم والتكنولوجيا والهندسة والرياضيات][wiki-STEM].
للوصول إلى جزأي العدد المركب كلٌّ على حدة:
z <- 2+3i
Re(z) # real part
#> [1] 2
Im(z) # imaginary part
#> [1] 3
يمكن أن يكون أي من الجزأين صفرًا، وقد يتحدث الرياضيون حينها عن عدد «حقيقي بالكامل» أو «تخيلي بالكامل». ومع ذلك، يبقى عددًا مركبًا في R.
1.2 + 0i
#> [1] 1.2+0i
typeof(1.2 + 0i)
#> [1] "complex"
2i
#> [1] 0+2i
typeof(2i)
#> [1] "complex"
ربما سمعت أن «i (أو j) هو الجذر التربيعي للعدد -1».
في الوقت الحالي، كل ما يعنيه هذا أن الجزء التخيلي بحكم التعريف يحقق المساواة التالية:
1i * 1i == -1 # more precisely, 1i * 1i == -1 + 0i
#> [1] TRUE
هذه فكرة بسيطة، لكنها تؤدي إلى نتائج مثيرة للاهتمام.
معظم العوامل المستخدمة مع الأعداد العشرية والأعداد الصحيحة تعمل أيضًا مع الأعداد المركبة:
z1 = 1.5 + 2i
z2 = 2 + 1.5i
z1 + z2 # addition
#> [1] 3.5+3.5i
z1 * z2 # multiplication
#> [1] 0+6.25i
z1 / z2 # division
#> [1] 0.96+0.28i
z1^2 # exponentiation
#> [1] -1.75+6i
2^z1 # another exponentiation
#> [1] 0.518895+2.780422i
معظم الدوال الرياضية تعمل مع المدخلات المركبة.
وهناك عدة دوال، إضافة إلى Re() وIm()، ذات صلة خاصة بالأعداد المركبة.
Conj() ببساطة إشارة الجزء التخيلي للعدد المركب (من + إلى - أو العكس).
abs(<complex number>) عددًا حقيقيًا بلا جزء تخيلي (وهو «مقدار» العدد)، وMod(<complex number>) مرادف لها.Arg(<complex number>) زاوية الطور بالراديان.z1
#> [1] 1.5+2i
abs(z1)
#> [1] 2.5
Mod(z1) # same as previous
#> [1] 2.5
Conj(z1) # flip sign
#> [1] 1.5-2i
Arg(z1)
#> [1] 0.9272952
لقد تم توظيفك للتو في شركة تاكسي جديدة تحاول أن تتميّز عن غيرها من الخدمات في سوق مشبع بالفعل. ولتحقيق ذلك، قرّر الرئيس التنفيذي تقديم خدمة فائقة الفخامة في مانهاتن، مع مضيفين عند كل تقاطع لمساعدة العملاء قبل رحلتهم وبعدها. والآن، عليك كتابة بعض الكود الذي سيساعد في تشغيل هذه الخدمة.
قرّر رئيسك التنفيذي أنه بما أن مانهاتن تتميز بتخطيط شوارع شبكي في معظمه، فإن الأعداد المركبة طريقة ملائمة لتمثيل تقاطعات الشوارع. حيث تمثّل الأعداد الحقيقية الموجبة والسالبة الشرق والغرب، وتمثّل الأعداد التخيلية الموجبة والسالبة الشمال والجنوب على الترتيب.
ولأن إنشاء عدد مركب في R أمر... فريد بعض الشيء، إن جاز التعبير، فقد طُلب منك تنفيذ دالة بسيطة للأعداد المركبة.
نفّذ الدالة simplex(a, b) التي تأخذ العددين الصحيحين a و b.
وأرجِع العدد المركب a+bi.
simplex(1, 1)
#> 1+1i
simplex(-3, 4)
#> -3+4i
عندما يعطي العميل تقاطع الوجهة، سيحصل سائقوك على إرشادات حول كيفية الوصول إلى هناك. تأتي هذه الإرشادات في صورة عدد مركب، حيث يمثّل الجزء الحقيقي عدد المربعات التي يجب قطعها شمالًا/جنوبًا، ويمثّل الجزء التخيلي المسافة شرقًا/غربًا. ولمواءمة البوصلة التقليدية، قرّر مدير مشروعك أن الشمال يكون في الاتجاه التخيلي الموجب، والجنوب في الاتجاه التخيلي السالب. وبالمثل، الشرق في الاتجاه الحقيقي الموجب، والغرب في الاتجاه الحقيقي السالب.
نفّذ الدالة driver_directions(start, end) التي تأخذ إحداثيات تقاطع البداية start وإحداثيات الوجهة end.
وأرجِع عددًا مركبًا يمثّل عدد المربعات شرقًا/غربًا + شمالًا/جنوبًا التي على السائق قطعها.
driver_directions(0+0i, 7+5i)
#> 7+5i
driver_directions(-2+3i, 4-5i)
#> 6-8i
يتقاضى العميل رسومًا مقابل المسافة التي يجب على التاكسي قطعها. ولأن مانهاتن تتميز بتخطيط شوارع شبكي، فلا تستطيع سيارات الأجرة السير إلا عبر هذه الطرق. ويؤدي هذا البنيان إلى مقياس مسافة مقيّد بالسير على خطوط الشبكة. ويمكن إيجاد المسافة بجمع عدد الخطوط المقطوعة أو عدد التقاطعات التي تم الوصول إليها (أي دون احتساب تقاطع البداية). ويُسمّى هذا المقياس عادةً مسافة مانهاتن أو معيار L1.
نفّذ الدالة manhattan(start, end) التي تأخذ تقاطعَي البداية start والوجهة end.
وأرجِع مسافة مانهاتن بين تقاطعَي start و end.
manhattan(0+0i, 3+4i)
#> 7
manhattan(-2-3i, -1+1i)
#> 5
تمكّن الرئيس التنفيذي من إقناع بنوك الاستثمار بالمشاركة بإبراز أن الخدمة ليست فائقة الفخامة فحسب، بل صديقة للبيئة أيضًا، لأنها ستستخدم غربانًا مدرّبة لنقل الرسائل بين المضيفين عند التقاطعات (والذين ينقلون بدورهم معلومات عن الركاب لتقديم تجربة شخصية). ويبدو أن لا أحد من مصرفيي الاستثمار قد كلّف نفسه عناء التحقق من سبب كون هذه الخدمة صديقة للبيئة بالضبط، ولا حتى من نوع الرئيس التنفيذي الذي يستمتع بتدريب الغربان في وقت فراغه، لأن أموال الاستثمار تتوافد بغزارة.
وتُحتسب رسوم هذه الخدمة أيضًا بحسب المسافة المقطوعة. ولكن بما أن الغربان تستطيع الطيران، فليس عليها اتباع شبكة الطرق ويمكنها أن تسلك أقصر مسار. وبالطبع، قد لا يكون الأمر كذلك عند وجود ناطحات سحاب ضخمة، لكن الرئيس التنفيذي يقيم هذه الخدمة في مانهاتن بولاية كنساس (المعروفة بـ"The Little Apple")، حيث تستطيع الغربان بسهولة الطيران فوق المباني المنخفضة. أما الطلب المحتمل على مثل هذه الخدمة في مانهاتن بولاية كنساس، وكيف سيشعر المارة المحليون بهذا العدد الكبير من الطيور تحلّق فوق رؤوسهم، فهما أمران ليوم آخر.
نفّذ الدالة as_crow_flies(start, end) التي تأخذ تقاطعَي start و end.
وأرجِع مسافة "كما يطير الغراب" بين النقطتين.
as_crow_flies(0+0i, 3+4i)
#> 5
درّب رئيسك التنفيذي الغربان على اتباع إرشادات مشابهة لإرشادات السائقين. غير أن الرئيس التنفيذي يعشق نصف الكرة الجنوبي، فدرّب الغربان باستخدام بوصلة مختلفة عن تلك التي يستخدمها مدير مشروعك لبقية النظام. واتضح أن رئيسك التنفيذي شخص غريب أطوار إلى حد كبير. ففي بوصلة الرئيس التنفيذي، يكون الشمال في الاتجاه التخيلي السالب، والجنوب في الاتجاه التخيلي الموجب. وهذا عكس اتجاهات الشمال/الجنوب عند السائقين، أما الشرق/الغرب فيبقيان كما هما.
نفّذ الدالة crows_directions(start, end) التي تأخذ تقاطعَي start و end.
وأرجِع العدد المركب المماثل لاتجاهات السائق، لكن مع عكس الشمال/الجنوب.
driver_directions(0+0i, 7+5i)
#> 7-5i
driver_directions(-2+3i, 4-5i)
#> 6+8i
سجّل في Exercism لتتعلّم وتتقن R عبر 21 مفهومًا111 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.