سؤال

لدي عبارة if بشرطين (مفصولين بعامل تشغيل OR)، يغطي أحد الشرطين +70% من المواقف ويستغرق وقتًا أقل بكثير للمعالجة/التنفيذ من الشرط الثاني، لذلك من أجل السرعة أريد فقط الشرط الثاني الذي سيتم معالجته إذا تم تقييم الشرط الأول على خطأ.

إذا قمت بترتيب الشروط بحيث يظهر الشرط الأول (الأسرع) في عبارة if أولاً - في المناسبات التي يتم فيها استيفاء هذا الشرط وتقييمه على أنه صحيح، فهل تتم معالجة الشرط الثاني؟

if ( (condition1) | (condition2) ){
  // do this
}

أو هل سأحتاج إلى دمج عبارات if للتحقق من الشرط الثاني فقط إذا تم تقييم الأول على خطأ؟

if (condition1){
  // do this
}else if (condition2){
  // do this
}

أنا أعمل في PHP، ومع ذلك، أفترض أن هذا قد يكون محايدًا للغة.

هل كانت مفيدة؟

المحلول

بالنسبة إلى C وC++ وC# وJava وغيرها من لغات .NET، يتم تحسين التعبيرات المنطقية بحيث لا يتم تقييم أي شيء آخر بمجرد معرفة ما يكفي.

كانت إحدى الحيل القديمة لتنفيذ التعليمات البرمجية المبهمة هي استخدام هذا لإنشاء عبارات if، مثل:

a || b();

إذا كان "a" صحيحًا، فلن يتم تقييم "b()" أبدًا، لذا يمكننا إعادة كتابته في:

if(!a)
    b();

وبالمثل:

a && b();

قد يصبح

if(a)
    b();

يرجى الملاحظة أن هذا صحيح فقط لـ || و && عامل.المشغلان | و & هو bitwise أو ، وبالتالي ، وبالتالي ليست "محسنة".

يحرر:كما ذكر الآخرون، فإن محاولة تحسين التعليمات البرمجية باستخدام منطق الدائرة القصيرة نادرًا ما تستغرق وقتًا طويلاً.

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

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

نصائح أخرى

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

يرى http://en.wikipedia.org/wiki/Short-circuit_evaluation

في C وC++ وJava، العبارة:

if (condition1 | condition2) {
  ...
}

سيتم تقييم كلا الشرطين في كل مرة ولن يكون صحيحًا إلا إذا كان التعبير بأكمله صحيحًا.

البيان:


if (condition1 || condition2) {
  ...
}

سيتم تقييم condition2 فقط اذا condition1 هو زائف.يكون الفرق كبيرًا إذا كان الشرط 2 عبارة عن دالة أو تعبير آخر له تأثير جانبي.

ومع ذلك، لا يوجد فرق بين || القضية و if/else قضية.

لقد رأيت الكثير من هذه الأنواع من الأسئلة مؤخرًا - التحسين إلى الدرجة التاسعة.

أعتقد أن هذا منطقي في ظروف معينة:

  1. حالة الحوسبة 2 ليست عملية زمنية ثابتة
  2. أنت تسأل لأغراض تعليمية فقط - فأنت تريد أن تعرف كيف تعمل اللغة، وليس لحفظ 3us.

في حالات أخرى، يكون القلق بشأن الطريقة "الأسرع" لتكرار الشرط الشرطي أو التحقق منه أمرًا سخيفًا.بدلاً من كتابة الاختبارات التي تتطلب ملايين التجارب لمعرفة أي اختلاف قابل للتسجيل (ولكنه غير مهم)، ركز على الوضوح.

عندما يلتقط شخص آخر (يمكن أن يكون أنت!) هذا الرمز خلال شهر أو عام، فإن الأمر الأكثر أهمية هو الوضوح.

في هذه الحالة، المثال الأول الخاص بك هو أقصر وأوضح ولا يتطلب منك تكرار نفسك.

وفق هذا المقال تقوم PHP بإجراء تقييم الدائرة القصيرة، مما يعني أنه إذا تم استيفاء الشرط الأول، فلن يتم تقييم الشرط الثاني.من السهل جدًا الاختبار أيضًا (من المقالة):

<?php
/* ch06ex07 – shows no output because of short circuit evaluation */

if (true || $intVal = 5) // short circuits after true
{

echo $intVal; // will be empty because the assignment never took place
}

?>

الدائرة القصيرة ليست للتحسين.والغرض الرئيسي منه هو تجنب استدعاء التعليمات البرمجية التي لن تعمل، ولكنها تؤدي إلى اختبار قابل للقراءة.مثال:

if (i < array.size() && array[i]==foo) ...

لاحظ أن المصفوفة [i] قد تتعرض لانتهاك الوصول إذا كنت خارج النطاق وتعطلت البرنامج.وبالتالي فإن هذا البرنامج بالتأكيد يعتمد على قصر عملية التقييم!

أعتقد أن هذا هو السبب وراء كتابة التعبيرات بهذه الطريقة في كثير من الأحيان أكثر من اهتمامات التحسين.

على الرغم من أن استخدام دوائر القصر لأغراض التحسين غالبًا ما يكون مبالغة، إلا أن هناك بالتأكيد أسباب مقنعة أخرى لاستخدامه.أحد الأمثلة على ذلك (في C++) هو ما يلي:

if( pObj != NULL && *pObj == "username" ) {
    // Do something...
}

وهنا يتم الاعتماد على قصر الدائرة الكهربائية لضمان ذلك pObj تم تخصيصها قبل إلغاء مرجعيتها.هذا أكثر إيجازًا بكثير من التداخل if صياغات.

وبما أن هذه لغة ملحدة، فسوف أتدخل فيها.بالنسبة لـ Perl على الأقل، الخيار الأول كافٍ، فأنا لست على دراية بـ PHP.يتم تقييمه من اليسار إلى اليمين وينسحب بمجرد استيفاء الشرط.

في معظم اللغات مع التحسين اللائق، سيعمل الأول بشكل جيد.

ال | هو عامل bitwise في PHP.هذا ليس ما اعنيه $a OR $b, ، بالضبط.سترغب في استخدام الأنبوب المزدوج.ونعم، كما ذكرنا، PHP تقوم بتقييم الدائرة القصيرة.وبطريقة مماثلة، إذا كان الشرط الأول ل && يتم تقييم الجملة إلى خطأ، ولا تقوم PHP بتقييم بقية الجملة أيضًا.

يحتوي VB.net على تعبيرين رائعين هما "OrElse" و"AndAlso"

ستقوم OrElse بتقصير دائرة نفسها في المرة الأولى التي تصل فيها إلى التقييم الحقيقي وتنفذ الكود الذي تريده.

If FirstName = "Luke" OrElse FirstName = "Darth" Then
   Console.Writeline "Greetings Exalted One!"
End If

وأيضًا سوف تقوم بتقصير دائرة نفسها في المرة الأولى التي تقوم فيها بتقييم خاطئ ولن تقوم بتقييم الكود داخل الكتلة.

If FirstName = "Luke" AndAlso LastName = "Skywalker" Then
   Console.Writeline "You are the one and only."
End If

أجد كلا من هذه مفيدة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top