c++ - test - تحديد ما إذا كان الرقم إما مضاعفات عشرة أو ضمن مجموعة معينة من النطاقات




live c++ (10)

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

احتاج -

if (num is a multiple of 10) { do this }

if (num is within 11-20, 31-40, 51-60, 71-80, 91-100) { do this }
else { do this } //this part is for 1-10, 21-30, 41-50, 61-70, 81-90

هذا هو لعبة الثعابين والسلالم ، إذا كان الأمر أكثر منطقية لسؤالي.

أتخيل أول جملة إذا كنت سأحتاج إلى استخدام المعامل ، هل سيكون if (num == 100%10) صحيحًا؟

الثاني ليس لدي أي فكرة. يمكنني أن أكتبه كما if (num > 10 && num is < 21 || etc) ولكن يجب أن يكون هناك شيء أكثر ذكاء من ذلك.


إذا (عدد الأسطوانات مضاعف 10) {فعل هذا}

if (num % 10 == 0) {
  // Do something
}

إذا كانت (num ضمن 11-20 ، 31-40 ، 51-60 ، 71-80 ، 91-100) {فعل هذا}

الخدعة هنا هي البحث عن نوع من القواسم المشتركة بين النطاقات. بالطبع ، يمكنك دائمًا استخدام طريقة "brute force":

if ((num > 10 && num <= 20) ||
    (num > 30 && num <= 40) ||
    (num > 50 && num <= 60) ||
    (num > 70 && num <= 80) ||
    (num > 90 && num <= 100)) {
  // Do something
}

ولكن قد تلاحظ أنه إذا قمت بطرح 1 من num ، فسوف يكون لديك النطاقات:

10-19, 30-39, 50-59, 70-79, 90-99

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

if ((num > 0) && (num <= 100) && (((num - 1) / 10) % 2 == 1)) {
  // Do something
}

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

وهو يساعد على افتراض المطور القادم للعمل على رمز مسلح ويعرف المكان الذي تعيش فيه. :-)


إذا كنت تستخدم GCC أو أي مترجم يدعم Case Ranges ، فيمكنك القيام بذلك ، ولكن التعليمات البرمجية لن تكون محمولة

switch(num)
{
case 11 ... 20:
case 31 ... 40:
case 51 ... 60:
case 71 ... 80:
case 91 ... 100:
    // do something
    break;
default:
    // do something else
    break;
}

الأول سهل ، تحتاج فقط إلى تطبيق مشغل modulo على قيمة العدد:

if ( ( num % 10 ) == 0)

S ++ c ++ بتقييم كل رقم ليس 0 كصحيح ، يمكنك أيضًا كتابة:

if ( ! ( num % 10 ) )  //does not have a residue when devided by 10

بالنسبة للجزء الثاني ، أعتقد أن هذا أكثر نظافةً لفهمه:

يتكرر النمط كل 20 ، بحيث يمكنك حساب modulo 20. جميع العناصر التي تريدها ستكون في صف ما عدا تلك القابلة للقسمة ب 20.

وللحصول عليها أيضًا ، استخدم فقط num-1 أو num + 19 لتجنب التعامل مع الأرقام السالبة.

if ( ( ( num + 19 ) % 20 ) > 9 )

هذا يفترض أن النمط يتكرر إلى الأبد ، لذلك بالنسبة لـ 111 إلى 120 ، فإنه ينطبق مرة أخرى ، وهكذا. وإلا فإنك تحتاج إلى تحديد الأرقام إلى 100:

if ( ( ( ( num + 19 ) % 20 ) > 9 ) && ( num <= 100 ) )

قد تكون تفكر في هذا.

if (x % 10)
{
   .. code for 1..9 ..
} else
{
   .. code for 0, 10, 20 etc.
}

السطر الأول if (x % 10) تعمل لأن (a) قيمة متعددة من 10 تحسب كـ '0' ، ينتج عن الأرقام الأخرى الباقي ، (ب) قيمة 0 في if تم اعتبارها false ، أي قيمة أخرى true .

تصحيح:

للتبديل ذهابًا وإيابًا في العشرينيات ، استخدم الحيلة نفسها. هذه المرة ، الرقم المحوري هو 10 :

if (((x-1)/10) & 1)
{
  .. code for 10, 30, ..
} else
{
   .. code for 20, 40, etc.
}

يعيد x/10 أي رقم من 0 إلى 9 كـ 0 ، 10 إلى 19 كـ 1 وما إلى ذلك. اختبار على حتى أو فردي - يخبرك & 1 - إذا كان حتى أو فردي. نظرًا لأن النطاقات الخاصة بك هي في الواقع "11 إلى 20" ، اطرح 1 قبل الاختبار.


لأول مرة ، للتحقق مما إذا كان الرقم متعدد الاستخدامات:

if (num % 10 == 0) // its divisible by 10

للثاني:

if(((num - 1) / 10) % 2 == 1 && num <= 100)

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

الآن بعد أن أعطيت فكرة أفضل عن ما تفعله ، سأكتب الثاني على أنه:

   int getRow(int num) {
      return (num - 1) / 10;   
   }

   if (getRow(num) % 2 == 0) {
   }

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


لقد أوضحت الإجابة بنفسك بشكل أساسي ولكن إليك الشفرة فقط.

if((x % 10) == 0) {
  //do this
}
if((x > 10 && x < 21) || (x > 30 && x < 41) || (x > 50 && x < 61) || (x > 70 && x < 81) || (x > 90 && x < 101)) {
  //do this
}

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

template<typename It, typename Elem>
bool in_any_interval(It first, It last, const Elem &val) {
    return std::any_of(first, last, [&val](const auto &p) {
        return p.first <= val && val <= p.second;
    });
}

من أجل البساطة ، استخدمت lambda متعددة الأشكال (C ++ 14) بدلاً من حجة pair صريحة. ربما ينبغي أيضًا الالتزام باستخدام < and == ليكون متسقًا مع الخوارزميات القياسية ، ولكنه يعمل على هذا النحو طالما أن Elem يملك <= مُحددًا له. على أي حال ، يمكن استخدامه على النحو التالي:

std::pair<int, int> intervals[]{
    {11, 20}, {31, 40}, {51, 60}, {71, 80}, {91, 100}
};

const int num = 15;
std::cout << in_any_interval(std::begin(intervals), std::end(intervals), num);

هناك مثال حي here .


وأنا أعلم أن هذا السؤال لديه الكثير من الإجابات ، ولكن سأطرح الألغام هنا على أي حال ... مأخوذ من الطبعة الكاملة الثانية لرمز ماكونيل: "جداول الوصول إلى درج الخطوة:
بعد نوع آخر من الوصول إلى الجدول هو طريقة درج الخطوة. طريقة الوصول هذه ليست مباشرة مثل بنية الفهرس ، ولكنها لا تضيع الكثير من مساحة البيانات. الفكرة العامة لهياكل السلالم ، كما هو موضح في الشكل 18-5 ، هي أن الإدخالات في الجدول صالحة لنطاقات البيانات بدلاً من نقاط البيانات المميزة.

الشكل 18-5 يقوم نهج خطوة الدرج بتصنيف كل إدخال عن طريق تحديد المستوى الذي يصطدم به "بالدرج". وتحدد "الخطوة" التي تصل إليها فئة هذه الفئة.

على سبيل المثال ، إذا كنت تكتب برنامج تقدير ، فقد يتراوح نطاق الدخول "B" من 75 إلى 90 في المائة. إليك مجموعة من الدرجات التي قد يتعين عليك إجراؤها يومًا ما:

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

على الرغم من أن هذا مثال بسيط ، يمكنك بسهولة تعميمه على التعامل مع العديد من الطلاب ، ومخططات الدرجات المتعددة (على سبيل المثال ، درجات مختلفة لمستويات نقاط مختلفة في مهام مختلفة) ، والتغييرات في نظام التقدير. "

الكود أكمل صفحات الإصدار الثاني 426 - 428 (الفصل 18). آمل أن يساعد هذا و آسف لم أقم بتحويل الكود في c ++ لكنك تعلم أن الصينية القديمة تقول: "لا تعطي السمك للمتسول ، أعطه قصبة الصيد!" :)


لأول واحد:

if (x % 10 == 0)

سوف ينطبق على:

10, 20, 30, .. 100 .. 1000 ...

للثاني:

if (((x-1) / 10) % 2 == 1)

سوف يتقدم بطلب:

11-20, 31-40, 51-60, ..

نحن في الأساس نقوم أولاً بـ x-1 للحصول على:

10-19, 30-39, 50-59, ..

ثم نقسمهم على 10 للحصول على:

1, 3, 5, ..

لذلك نتحقق مما إذا كانت هذه النتيجة غريبة.


نداء من أجل القراءة

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

هذا هو التفاف أي عبارات "ذكية" في وظيفة تظهر بالضبط (مع اسمها) ما تقوم به. في حين أن هناك تأثير ضئيل على الأداء (من "وظيفة استدعاء الحمل") هذا لا يكاد يذكر في حالة لعبة مثل هذا.

على طول الطريق ، يمكنك تطهير مدخلاتك - على سبيل المثال ، اختبار القيم "غير القانونية". وبالتالي قد ينتهي بك الأمر مع رمز مثل هذا - انظر كم هو أكثر قابلية للقراءة؟ يمكن إخفاء "وظائف المساعد" في مكان ما (لا يلزم أن تكون في الوحدة الرئيسية: يتضح من أسمائهم ما يفعلونه):

#include <stdio.h>

enum {NO, YES, WINNER};
enum {OUT_OF_RANGE=-1, ODD, EVEN};

int notInRange(int square) {
  return(square < 1 || square > 100)?YES:NO;
}

int isEndOfRow(int square) {
  if (notInRange(square)) return OUT_OF_RANGE;
  if (square == 100) return WINNER; // I am making this up...
  return (square % 10 == 0)? YES:NO;
}

int rowType(unsigned int square) {
  // return 1 if square is in odd row (going to the right)
  // and 0 if square is in even row (going to the left)
  if (notInRange(square)) return OUT_OF_RANGE; // trap this error
  int rowNum = (square - 1) / 10;
  return (rowNum % 2 == 0) ? ODD:EVEN; // return 0 (ODD) for 1-10, 21-30 etc.
                                       // and 1 (EVEN) for 11-20, 31-40, ...
}

int main(void) {
  int a = 12;
  int rt;
  rt = rowType(a); // this replaces your obscure if statement

  // and here is how you handle the possible return values:
  switch(rt) {
  case ODD:
    printf("It is an odd row\n");
    break;
  case EVEN:
    printf("It is an even row\n");
    break;
  case OUT_OF_RANGE:
    printf("It is out of range\n");
    break;
  default:
    printf("Unexpected return value from rowType!\n");
  }

  if(isEndOfRow(10)==YES) printf("10 is at the end of a row\n");
  if(isEndOfRow(100)==WINNER) printf("We have a winner!\n");
}




integer-arithmetic