برنامج حاسوبي (dc)

dc ( آلة حاسبة مكتبية ) هي آلة حاسبة متعددة المنصات مكتوبة بلغة بولندية معكوسة، تدعم العمليات الحسابية بدقة اختيارية . [ 1 ] طُوِّرت بواسطة لوريندا تشيري وروبرت موريس في مختبرات بيل . [ 2 ] تُعدّ dc من أقدم أدوات يونكس ، حتى أنها سبقت تطوير لغة البرمجة C. وكغيرها من الأدوات القديمة، تتميز dc بمجموعة قوية من الميزات، ولكن بصياغة مختصرة. [ 3 ] [ 4 ] على الرغم من أن برنامج الآلة الحاسبة bc (الذي يستخدم تدوينًا وسطيًا ) كان يُنفَّذ تقليديًا باستخدام dc، إلا أن تطبيق GNU الحديث لـ dc يعتمد على bc. [ 5 ]

تاريخ

يُعدّ برنامج dc أقدم برنامج مكتوب بلغة يونكس لا يزال يعمل حتى اليوم . عندما استلمت مختبرات بيل ، حيث طُوّر برنامج dc، جهاز PDP-11 ، كان برنامج dc - المكتوب بلغة B - أول برنامج يُشغّل على هذا الحاسوب الجديد، حتى قبل ظهور برنامج التجميع. [ 2 ] وقد أشار كين تومسون إلى أن برنامج dc كان أول برنامج كُتب على هذا الجهاز. [ 6 ]

العمليات الأساسية

لضرب أربعة وخمسة في العدد ذي المضاعفة (لاحظ أن معظم المسافة البيضاء اختيارية):

$ cat << EOF > cal.txt 4 5 * p EOF$ dc cal.txt 20 $

تتوفر النتائج أيضًا من خلال الأوامر التالية:

$ echo "4 5 * p" | dc 

أو

$ dc - 4 5*pq 20$ dc 4 5 * p 20 q$ dc -e '4 5 * p'

يُترجم هذا إلى: "أضف العددين 4 و5 إلى المكدس، ثم باستخدام عامل الضرب، اسحب عنصرين من المكدس، واضربهما، وأضف الناتج إلى المكدس". بعد ذلك، pيُستخدم الأمر لفحص (طباعة) العنصر العلوي في المكدس. qيُنهي الأمر تشغيل نسخة dc المُستدعاة. لاحظ أنه يجب ترك مسافة بين الأرقام، بينما لا يشترط ذلك في بعض العوامل.

يتم تغيير دقة العمليات الحسابية باستخدام الأمر k، الذي يحدد عدد الأرقام العشرية (عدد الأرقام التي تلي الفاصلة العشرية ) المستخدمة في العمليات الحسابية. وبما أن الدقة الافتراضية هي صفر، فإن سلسلة الأوامر هذه تُنتج 0النتيجة التالية:

2 3 / ص 

من خلال ضبط الدقة باستخدام k، يمكن إنتاج عدد غير محدود من المنازل العشرية. ينتج عن تسلسل الأوامر هذا .66666.

5 كيلومترات 2 3 / ص 

لتقييم(12+(-3)4)11-22{\displaystyle {\sqrt {\left(12+\left(-3\right)^{4}\right) \over 11}}-22}: ( vيحسب الجذر التربيعي لأعلى عنصر في المكدس _ويستخدم لإدخال عدد سالب):

12 _3 4 ^ + 11 / v 22 - ص 

لتبديل العنصرين العلويين في المكدس، استخدم rالأمر. لتكرار العنصر العلوي، استخدم dالأمر.

المدخلات/المخرجات

لقراءة سطر من المدخلات القياسية (stdin) ، استخدم ?الأمر. يُقيّم هذا الأمر السطر كما لو كان أمر dc، لذا من الضروري أن يكون صحيحًا نحويًا، ويُشكّل مشكلة أمنية محتملة لأن !أمر dc يسمح بتنفيذ أوامر عشوائية.

كما ذُكر أعلاه، pيطبع هذا الأمر الجزء العلوي من المكدس مع سطر جديد بعده. nويسحب هذا الأمر الجزء العلوي من المكدس ويطبعه بدون سطر جديد في نهايته. fويطبع هذا الأمر المكدس بأكمله مع إدخال واحد في كل سطر.

يدعم الأمر dc أيضًا أي أساس إدخال وإخراج . iيقوم الأمر بسحب العنصر العلوي من المكدس واستخدامه كأساس للإدخال. يجب أن تكون الأرقام الست عشرية بأحرف كبيرة لتجنب التعارض مع أوامر dc، وهي محدودة بـ AF. oيقوم الأمر بنفس الشيء بالنسبة لأساس الإخراج، ولكن تذكر أن أساس الإدخال يؤثر على تحليل كل قيمة عددية لاحقة، لذا يُنصح عادةً بتعيين أساس الإخراج أولًا. لذلك، 10oيضبط أساس الإخراج على أساس الإدخال الحالي، ولكن ليس عادةً على 10. ومع ذلك، Aoيعيد الأمر ضبط أساس الإخراج إلى 10، بغض النظر عن أساس الإدخال. لقراءة القيم، Kتقوم Iالأوامر Oبدفع الدقة الحالية، وأساس الإدخال، وأساس الإخراج إلى أعلى المكدس.

على سبيل المثال، لتحويل البيانات من النظام الست عشري إلى النظام الثنائي:

$ echo 16i2o DEADBEEFp | dc 11011110101011011011111011101111

خصائص اللغة

السجلات

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

تعتمد آلية عمل وحدات الماكرو والشروط على السجل ، وهو في لغة البرمجة DC موقع تخزين يحمل اسمًا مكونًا من حرف واحد، ويمكن تخزين البيانات فيه واسترجاعها منه: scحيث يقوم النظام بسحب أعلى عنصر من المكدس وتخزينه في السجل c، ثم lcيدفع قيمة السجل c إلى المكدس. على سبيل المثال:

3 sc 4 ​​lc * p 

يمكن أيضًا التعامل مع السجلات على أنها مكدسات ثانوية، لذا يمكن دفع القيم وسحبها بينها وبين المكدس الرئيسي باستخدام Sالأوامر L.

الأوتار

تُحاط القيم النصية بأحرف [ASCII ]، ويمكن إضافتها إلى المكدس وتخزينها في المسجلات. aيحوّل الأمر البايت الأدنى من القيمة العددية إلى حرف ASCII ، أو إذا كان الجزء العلوي من المكدس نصيًا، فإنه يستبدله بالحرف الأول من النص. لا توجد طرق أخرى لإنشاء سلاسل نصية أو معالجتها سوى تنفيذها باستخدام الأمر x، أو طباعتها باستخدام Pالأمر.

تبدأ الشخصية #بالتعليق حتى نهاية السطر.

وحدات الماكرو

يتم تنفيذ وحدات الماكرو بالسماح بأن تكون سجلات النظام ومدخلات المكدس عبارة عن سلاسل نصية بالإضافة إلى الأرقام. يمكن طباعة السلسلة النصية، ولكن يمكن أيضًا تنفيذها (أي معالجتها كسلسلة من أوامر dc). على سبيل المثال، يمكننا تخزين ماكرو لإضافة واحد ثم ضرب الناتج في 2 في السجل m.

[1 + 2 *] sm 

وبعد ذلك (باستخدام xالأمر الذي ينفذ الجزء العلوي من المكدس) يمكننا استخدامه على النحو التالي:

3 لومن إكس بي 

الشروط

أخيرًا، يمكننا استخدام آلية الماكرو هذه لإضافة شروط. يقوم الأمر =rبسحب قيمتين من المكدس، وينفذ الماكرو المخزن في السجل rفقط إذا كانتا متساويتين. لذا، يطبع هذا الأمر السلسلة equalفقط إذا كانت القيمتان العلويتان في المكدس متساويتين.

[[equal]p] sr 5 5 =r 

تتضمن الشروط الأخرى ما يلي >: ، !>، <، !<، !=، والتي تُنفذ الماكرو المُحدد إذا كانت القيمتان العلويتان في المكدس أكبر من، أو أصغر من أو تساوي ("ليس أكبر")، أو أصغر من، أو أكبر من أو تساوي ("ليس أصغر من")، أو لا تساوي، على التوالي. لاحظ أن ترتيب المعاملات في مقارنات عدم المساواة هو عكس ترتيبها في العمليات الحسابية؛ 5 3 -حيث تُقيّم إلى 5 - 3 = 2، ولكنها تُنفذ محتويات السجل لأن .5 3 <tt3 < 5

الحلقات

يمكن تحقيق التكرار عن طريق تعريف ماكرو يقوم (بشرط) بإعادة استدعاء نفسه. يمكن تنفيذ مضروب بسيط لأعلى المكدس على النحو التالي:

# F(x): أعد x! # إذا كان x-1 > 1 # إرجاع x * F(x-1) # خلاف ذلك إرجاع x [d1-d1<F*]dsFxp 

يُنهي الأمر 1Qتنفيذ ماكرو، مما يسمح بالعودة المبكرة. qويُنهي تنفيذ الماكرو من مستويين (ويُنهي تنفيذه نفسه إذا كان عدد مستويات مكدس الاستدعاءات أقل من مستويين). zويُضيف عمق المكدس الحالي قبل zتنفيذ العملية.

أمثلة

جمع المكدس بأكمله

يتم تنفيذ ذلك باستخدام ماكرو مُخزّن في سجل، aيستدعي نفسه شرطيًا، ويُجري عملية جمع في كل مرة، حتى تبقى قيمة واحدة فقط في المكدس. zيُستخدم عامل التشغيل لدفع عدد العناصر في المكدس إلى المكدس. أما عامل المقارنة >فيُزيل قيمتين من المكدس لإجراء المقارنة.

العاصمة -e "1 2 4 8 16 100 0d[+z1<a]dsaxp"

والنتيجة هي 131.

جمع جميع تعبيرات DC كأسطر من الملف

الرقم المجرد هو تعبير dc صالح، لذلك يمكن استخدامه لجمع ملف يحتوي كل سطر فيه على رقم واحد.

يتم تنفيذ هذا مرة أخرى باستخدام ماكرو مخزن في السجل aيقوم باستدعاء نفسه بشكل مشروط، ويقوم بعملية جمع في كل مرة، حتى تبقى قيمة واحدة فقط على المكدس.

dc -e "0d[?+z1<a]dsaxp" < ملف 

يقرأ المُشغِّل ?أمرًا آخر من دفق الإدخال. إذا احتوى سطر الإدخال على عدد عشري، تُضاف هذه القيمة إلى المكدس. عندما يصل ملف الإدخال إلى نهايته، يكون الأمر فارغًا، ولا تُضاف أي قيمة إلى المكدس.

{ echo "5" ; echo "7" ; } | dc -e "0d[?+z1<a]dsaxp"

والنتيجة هي 12.

يمكن أن تكون خطوط الإدخال أيضًا أوامر تيار مستمر معقدة.

{ echo "3 5 *" ; echo "4 3 *" ; echo "5dd++" ; } | dc -e "0d[?+z1<a]dsaxp"

والنتيجة هي 42.

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

من عيوب هذا الحل: أن الحلقة تتوقف عند مصادفة سطر فارغ في دفق الإدخال (تقنيًا، أي سطر إدخال لا يضيف قيمة عددية واحدة على الأقل إلى المكدس)؛ وللتعامل مع الأعداد السالبة، يجب استبدال علامة السالب (-) في بداية دفق الإدخال بعلامة الشرطة السفلية (_)، نظرًا لعدم توافق إشارة السالب في مكتبة dc مع المعايير القياسية. كما أن عامل ?التشغيل في مكتبة dc لا يوفر طريقة واضحة للتمييز بين قراءة سطر فارغ وقراءة نهاية الملف.

تحويل الوحدات

كمثال على برنامج بسيط نسبيًا في نظام التشغيل DC، هذا الأمر (في سطر واحد):

dc -e '[[أدخل رقمًا (بالمتر)، أو 0 للخروج]PAP]sh[q]sz[lhx?d0=zAk.0254/.5+0kC~1/rn[ قدم ]Pn[ بوصة]PAPdx]dx'

يقوم بتحويل المسافات من الأمتار إلى الأقدام والبوصات؛ ويتعلق الجزء الأكبر منه بطلب الإدخال، وطباعة المخرجات بتنسيق مناسب، والتكرار لتحويل رقم آخر.

القاسم المشترك الأكبر

كمثال على ذلك، إليك تطبيق لخوارزمية إقليدس لإيجاد القاسم المشترك الأكبر :

dc -e '??[dSarLa%d0<a]dsax+p' # أقصر صيغة dc -e '[a=]P?[b=]P?[dSarLa%d0<a]dsax+[GCD:]Pp' # صيغة أسهل للقراءة

مضروب

حساب مضروب قيمة مُدخلة،ن!=أنا=1نأنا{\displaystyle n!=\prod _{i=1}^{n}i}

dc -e '?[q]sQ[d1=Qd1-lFx*]dsFxp'

كوينز في واشنطن العاصمة

توجد أيضًا برامج تُسمى "quines" في لغة البرمجة "dc"؛ وهي برامج تُنتج شفرة المصدر الخاصة بها كناتج.

dc -e '[91Pn[dx]93Pn]dx' dc -e '[91PP93P[dx]P]dx'

طباعة جميع الأعداد الأولية

dc -e '2p3p[dl!d2+s!%0=@l!l^!<#]s#[s/0ds^]s@[p]s&[ddvs^3s!l#x0<&2+lx]ds.x'

كتب هذا البرنامج ميشيل شاربنتييه، وهو يُخرج سلسلة من الأعداد الأولية. تجدر الإشارة إلى إمكانية وجود نسخة مختصرة منه، تتطلب أربعة عشر رمزًا أقل.

dc -e '2p3p[pq]s$[l!2+ds!l^<$dl!%0<#]s#[+dvs^1s!l#x2l.x]ds.x'

تحليل الأعداد الصحيحة إلى عواملها الأولية

dc -e '[n=]P?[p]s2[lip/dli%0=1dvsr]s12sid2%0=13sidvsr[dli%0=1lrli2+dsi!>.]ds.xd1<2'

وقد كتب هذا البرنامج أيضاً ميشيل شاربنتييه. [ 7 ]

هناك نسخة أقصر

dc -e "[n=]P?[lfp/dlf%0=Fdvsr]sF[dsf]sJdvsr2sf[dlf%0=Flfdd2%+1+sflr<Jd1<M]dsMx"

وحل أسرع (جرب مع الرقم 200 بت 2 200 -1 (المدخل 2 200^1-)

dc -e "[n=]P?[lfp/dlf% 0=Fdvsr]sFdvsr2sfd2%0=F3sfd3%0=F5sf[dlf%0=Flfd4+sflr>M]sN[dlf%0=Flfd2+sflr>N]dsMx[p]sMd1<M"

لاحظ أنه يمكن تسريع العملية الأخيرة بشكل أكبر، إذا تم استبدال الوصول إلى ثابت بالوصول إلى سجل.

dc -e "[n=]P?[lfp/dlf%l0=Fdvsr]sF2s2dvsr2sf4s4d2%0=F3sfd3%0=F5sf[dlf%l0=Flfdl4+sflr>M]sN[dlf%l0=Flfdl2+sflr>N]dsMx[p]sMd1<M"

حساب باي

تطبيق لخوارزمية تشودنوفسكي بلغة البرمجة dc. سيطبع البرنامج تقريبات أفضل فأدق أثناء تشغيله. ولكن بما أن باي عدد متسامٍ، فسيستمر البرنامج في العمل حتى يتم إيقافه أو استنفاد موارد الجهاز الذي يُشغّل عليه.

dc -e '_640320[0ksslk3^16lkd12+sk*-lm*lhd1+sh3^/smlxlj*sxll545140134+dsllm*lxlnk/ls+dls!=P]sP3^sj7sn[6sk1ddshsxsm13591409dsllPx10005v426880*ls/K3-k1/pcln14+snlMx]dsMx'

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

dc -e '1Sk1SR13591409dSBSP426880dSQ4/3^9*SC[0r-]s-[lkE*1-k10005vlQ*lP/nAan0k]dSox[Lkd1+Skdd1+Sk3^lC*SQ2*1-d3*d*4-*dSR545140134LB+dSB*lk2%0=-SP]dszx[LRLRdLP*LPLQdLQ*SQ*+SP*SR]sc[d1-d0<yd0<yd0=z0=zlcx]sy0[lcxlox1+lyxllx]dslx'

تبادل مفاتيح ديفي-هيلمان

يُعدّ استخدام dc مثالًا أكثر تعقيدًا مُدمجًا في نص برمجي مكتوب بلغة Perl، حيث يُجري عملية تبادل مفاتيح Diffie-Hellman . وقد شاع استخدامه ككتلة توقيع بين مُستخدمي التشفير خلال مناقشات ITAR ، حيث كان من الممكن تشغيل النص البرمجي القصير باستخدام Perl وdc فقط، وهما برنامجان شائعان على أنظمة التشغيل الشبيهة بنظام Unix: [ 8 ]

#!/usr/bin/env perl -- -export-a-crypto-system-sig Diffie-Hellman-2-lines ( $g , $e , $m ) = @ARGV , $m || die "$0 gen exp mod\n" ; print `echo "16dio1[d2%Sa2/d0<X+d*La1=z\U$m%0]SX$e"[$g*]\EszlXx+p | dc`

النسخة المُعلّقة أسهل فهمًا بعض الشيء، وتُبيّن كيفية استخدام الحلقات والشروط وأمر qالعودة من الماكرو. مع إصدار GNU من dc، |يُمكن استخدام الأمر لإجراء عملية أسية نمطية بدقة عشوائية دون الحاجة إلى كتابة دالة X.

معروف!/usr/bin/env perlmy ( $g , $e , $m ) = map { "\U$_" } @ARGV ; die "$0 gen exp mod\n" unless $m ;print `echo $g $e $m | dc -e ' # إدخال وإخراج سداسي عشري 16dio # قراءة m و e و g من الإدخال القياسي في سطر واحد ?SmSeSg# الدالة z: تُرجع g * أعلى المكدس [lg*]sz# الدالة Q: إزالة أعلى المكدس وإرجاع 1 [sb1q]sQ# الدالة X(e): حساب g^e % m بشكل متكرر # هي نفسها Sm^Lm%، ولكنها تتعامل مع أسس كبيرة بشكل تعسفي. # المكدس عند الدخول: e # المكدس عند الخروج: g^e % m # بما أن e قد تكون كبيرة جدًا، فإن هذه الدالة تستخدم الخاصية g^e % m == # إذا كان (e == 0) # أرجع 1 # x = (g^(e/2)) ^ 2 # إذا كان (e % 2 == 1) # x *= g # أرجع x % [  d 0=Q # أرجع 1 إذا كان e==0 (وإلا، المكدس: e)  d 2% Sa # تخزين e%2 في a (المكدس: e)  2/ # حساب e/2  lXx # استدعاء X(e/2)  d* # حساب X(e/2)^2  La1=z # الضرب في g إذا كان e%2==1  lm % # حساب (g^e) % m ] SXle # تحميل e من المسجل lXx # حساب g^e % m p # طباعة النتيجة '` ;

متغيرات البيئة

إذا كان متغير البيئة DC_LINE_LENGTH موجودًا ويحتوي على عدد صحيح أكبر من 1 وأصغر من216-1{\displaystyle 2^{16}-1}سيتم تقييد إخراج الأرقام (وفقًا لقاعدة الإخراج) بهذه القيمة، مع إدراج الشرطات المائلة العكسية والأسطر الجديدة بعد ذلك. طول السطر الافتراضي هو 70. القيمة الخاصة 0 تُعطّل فواصل الأسطر.

انظر أيضاً

مراجع

  1. : آلة حاسبة ذات دقة عشوائية دليل أوامر مستخدم لينكسdc(1)   
  2. 1 2 ماكيلروي، دكتور في الطب (1987). قارئ أبحاث يونكس: مقتطفات مشروحة من دليل المبرمج، 1971-1986 (ملف PDF) (تقرير فني). مختبرات بيل. 139.
  3. "مصادر صفحة الدليل الخاصة بالإصدار السابع من يونكس دي سي" . مؤرشفة من الأصل بتاريخ 23 أغسطس 2004. تم الاطلاع عليها بتاريخ 23 يونيو 2004 .
  4. ريتشي، دينيس م. (سبتمبر 1979). "تطور نظام المشاركة الزمنية في يونكس" . مؤرشف من الأصل في 2010-05-06.
  5. "GNU bc" . تم الاسترجاع في 25-01-2025 .
  6. برايان كيرنيغان وكين تومسون. متعةٌ لعشاق التقنية من حضور مهرجان الحواسيب القديمة 2019: كيرنيغان يُجري مقابلة مع تومسون حول نظام يونكس . يوتيوب. يبدأ الحدث عند الدقيقة 29 و45 ثانية . تم الاطلاع عليه في 3 سبتمبر 2019 .
  7. "دليل برمجة باش المتقدمة، الفصل 16، المثال 16-52 (التحليل إلى عوامل)" . تم الاطلاع عليه بتاريخ 2020-09-20 .
  8. آدم باك. "خوارزمية ديفي-هيلمان في سطرين من لغة بيرل" . تم الاطلاع عليه بتاريخ 5 يناير 2009 .