অন্যথায় বিবৃতিতে স্যুইচ ওভারের সুবিধা


168

৩০ টি গণনার জন্য switchএকটি ifস্টেটমেন্ট ব্যবহার করে একটি বিবৃতি ব্যবহারের জন্য সর্বোত্তম অনুশীলনটি কী unsignedযেখানে প্রায় 10 টির মধ্যে প্রত্যাশিত ক্রিয়া থাকে (এটি বর্তমানে একই ক্রিয়া)। পারফরম্যান্স এবং স্থান বিবেচনা করা প্রয়োজন তবে সমালোচনা নয়। আমি স্নিপেটটি বিমূর্ত করেছি তাই নামকরণের সম্মেলনে আমাকে ঘৃণা করবেন না।

switch বিবৃতি:

// numError is an error enumeration type, with 0 being the non-error case
// fire_special_event() is a stub method for the shared processing

switch (numError)
{  
  case ERROR_01 :  // intentional fall-through
  case ERROR_07 :  // intentional fall-through
  case ERROR_0A :  // intentional fall-through
  case ERROR_10 :  // intentional fall-through
  case ERROR_15 :  // intentional fall-through
  case ERROR_16 :  // intentional fall-through
  case ERROR_20 :
  {
     fire_special_event();
  }
  break;

  default:
  {
    // error codes that require no additional action
  }
  break;       
}

if বিবৃতি:

if ((ERROR_01 == numError)  ||
    (ERROR_07 == numError)  ||
    (ERROR_0A == numError)  || 
    (ERROR_10 == numError)  ||
    (ERROR_15 == numError)  ||
    (ERROR_16 == numError)  ||
    (ERROR_20 == numError))
{
  fire_special_event();
}

26
এটি 'সাবজেক্টিভ' হিসাবে সম্পাদিত হয়? সত্যি? অবশ্যই 'সাবজেক্টিভ' এমন কিছুর জন্য যা একরকম বা অন্যভাবে প্রমাণিত হতে পারে না?
আলেকজান্দ্রা ফ্রাঙ্কস

নিশ্চিত যে আপনি এটি সবচেয়ে কার্যকর কোড উত্পন্ন বিন্দু থেকে দেখতে পারেন, তবে যে কোনও আধুনিক সংকলক সমান দক্ষ হতে হবে। শেষ পর্যন্ত, এটি সাইকেলের শেডের রঙ সম্পর্কে আরও প্রশ্ন।
jfs

8
আমি দ্বিমত পোষণ করছি, আমি মনে করি না এটি বিষয়গত। একটি সাধারণ এএসএম পার্থক্য বিষয়, আপনি কেবলমাত্র বেশ কয়েকটি ক্ষেত্রে অপরিহার্যতার কয়েক সেকেন্ড উপেক্ষা করতে পারবেন না। এবং এই প্রশ্নে এটি কোনও ধর্মীয় যুদ্ধ বা বিতর্ক নয়, কেন দ্রুততর হবে তার যৌক্তিক ব্যাখ্যা রয়েছে, কেবল গ্রহণযোগ্য উত্তরটি পড়ুন।
চકૃત


@ রিচার্ডফ্রান্সস অফটপিক: গ্রেটস! আমি এর আগে
মডারেশনকে

উত্তর:


162

সুইচ ব্যবহার করুন।

সবচেয়ে খারাপ ক্ষেত্রে সংকলকটি if-other চেইনের মতো একই কোড তৈরি করবে, যাতে আপনি কোনও কিছু হারাবেন না। সন্দেহ হলে সর্বাধিক সাধারণ কেসগুলি প্রথমে স্যুইচ বিবৃতিতে রাখুন।

সর্বোত্তম ক্ষেত্রে অপ্টিমাইজার কোডটি উত্পন্ন করার জন্য আরও ভাল উপায় খুঁজে পেতে পারে। একটি কম্পাইলার সাধারণ কাজগুলি বাইনারি সিদ্ধান্ত গাছ (গড়ের তুলনায় তুলনামূলকভাবে লাফ দেয়) বা কেবল একটি লাফ-টেবিল তৈরি করে (কোনও তুলনা ছাড়াই কাজ করে)।


2
প্রযুক্তিগতভাবে এনামের মান জাম্প টেবিলের মধ্যে রয়েছে তা নিশ্চিত করার জন্য এখনও একটি তুলনা থাকবে।
0124816

Jep। সেটা সত্য. এনামগুলিতে স্যুইচিং এবং সমস্ত কেস পরিচালনা করা শেষ তুলনা থেকে মুক্তি পেতে পারে।
নিলস পিপেনব্রিংক

4
নোট করুন যে কোনও সংকলক দ্বারা স্যুইচ হিসাবে একই হিসাবে তাত্ত্বিকভাবে আইএফগুলির একটি সিরিজ বিশ্লেষণ করা যেতে পারে, তবে কেন সুযোগটি গ্রহণ করবেন? একটি স্যুইচ ব্যবহার করে আপনি ঠিক কী চান তা যোগাযোগ করছেন যা কোড উত্পন্নকরণকে আরও সহজ করে তোলে।
jakobengblom2

5
জাকোবেন: এটি করা যেতে পারে তবে কেবল স্যুইচ-এর মতো / অন্য চেইনগুলির জন্য। অনুশীলনে এগুলি ঘটে না কারণ প্রোগ্রামাররা স্যুইচ ব্যবহার করে। আমি সংকলক প্রযুক্তিতে খনন করেছি এবং আমার উপর বিশ্বাস রাখি: এই জাতীয় "অকেজো" নির্মাণগুলি খুঁজতে অনেক সময় লাগে time সংকলক ছেলের জন্য যেমন একটি অপ্টিমাইজেশন মোটামুটি তোলে।
নীলস পাইপেনব্রিন্ক

5
@ নীলপিপেনব্রিন্ক সিউডো-রিকার্সিভ if- elseটেম্পলেট মেটা প্রোগ্রামিংয়ের চেইনগুলি এবং চেইন তৈরির অসুবিধা সহকারে সহজেই switch caseএই ম্যাপিংটি আরও গুরুত্বপূর্ণ হয়ে উঠতে পারে with (এবং হ্যাঁ, প্রাচীন মন্তব্য, তবে ওয়েব চিরদিনের জন্য, বা কমপক্ষে আগামী মঙ্গলবার পর্যন্ত)
ইয়াক্ক - অ্যাডাম নেভ্রামাউন্ট

45

আপনি আপনার উদাহরণে যে বিশেষ ক্ষেত্রে সরবরাহ করেছেন তার জন্য, সবচেয়ে পরিষ্কার কোডটি সম্ভবত:

if (RequiresSpecialEvent(numError))
    fire_special_event();

স্পষ্টতই এটি সমস্যাটি কেবল কোডের একটি পৃথক অঞ্চলে নিয়ে যায়, তবে এখন আপনার এই পরীক্ষাটি পুনরায় ব্যবহার করার সুযোগ রয়েছে। কীভাবে এটি সমাধান করা যায় তার জন্য আপনার আরও বিকল্প রয়েছে। আপনি std :: সেট ব্যবহার করতে পারেন, উদাহরণস্বরূপ:

bool RequiresSpecialEvent(int numError)
{
    return specialSet.find(numError) != specialSet.end();
}

আমি প্রস্তাব দিচ্ছি না যে এটি প্রয়োজনীয় স্পেশালইভেন্টের সেরা প্রয়োগ, কেবল এটি একটি বিকল্প। আপনি এখনও একটি স্যুইচ বা যদি-অন্য শৃঙ্খলা, বা একটি সন্ধানের টেবিল, বা মানটিতে কিছুটা বিট-ম্যানিপুলেশন ব্যবহার করতে পারেন। আপনার সিদ্ধান্ত প্রক্রিয়াটি যতই অস্পষ্ট হবে, কোনও বিচ্ছিন্ন কার্যক্রমে আপনি এটির থেকে বেশি মূল্য অর্জন করবেন।


5
এটাই সত্যি. স্যুইচ এবং if-বিবৃতি উভয়ের চেয়ে পঠনযোগ্যতা অনেক ভাল। আমি আসলে নিজেই এর মতো কিছু উত্তর দিতে যাচ্ছিলাম তবে আপনি আমাকে এটির কাছে প্রহার করলেন। :-)
মেলারসন

যদি আপনার এনাম মানগুলি সমস্ত ছোট হয় তবে আপনার একটি হ্যাশ দরকার নেই, কেবল একটি টেবিল। যেমন const std::bitset<MAXERR> specialerror(initializer); এটি দিয়ে ব্যবহার করুন if (specialerror[numError]) { fire_special_event(); }। আপনি যদি সীমা-চেক করতে চান তবে সীমার bitset::test(size_t)বাইরে থাকা মানগুলিকে ব্যতিক্রম করবে। ( bitset::operator[]পরিসীমা-চেক না)। cplusplus.com/references/bitset/bitset/test । এটি সম্ভবত একটি সংকলক উত্পাদিত জাম্প টেবিল বাস্তবায়নকে ছাড়িয়ে যাবে switch, esp। বিশেষ-বিশেষ ক্ষেত্রে যেখানে এটি একক নয়-নেওয়া শাখা হবে।
পিটার কর্ডেস

@ পিটারকর্ডস আমি এখনও যুক্তি দিচ্ছি যে টেবিলটি তার নিজস্ব ফাংশনে রাখা ভাল। আমি যেমন বলেছি, প্রচুর অপশন রয়েছে যা আপনি যখন এটি করেন তখন খুলে যায়, আমি সেগুলি সমস্ত গণনার চেষ্টা করি নি।
মার্ক রেনসম

@ মার্করানসাম: আমি এটি বিমূর্ত করার সাথে একমত হতে চাইনি। আপনি যেহেতু একটি নমুনা বাস্তবায়ন দিয়েছিলেন std::set, আমি ভেবেছিলাম আমি এটি উল্লেখ করব যে এটি সম্ভবত একটি খারাপ পছন্দ। দেখা যাচ্ছে যে জিসিসি তত্ক্ষণাত 32 বিবিতে একটি বিটম্যাপটি পরীক্ষা করতে ওপির কোডটি কম্পাইল করে। গডবোল্ট: goo.gl/qjjv0e । gcc 5.2 এমনকি ifসংস্করণটির জন্য এটি করবে । এছাড়াও, আরও সাম্প্রতিক জিসিসি কিছুটা সঠিক স্থানে রাখার জন্য এবং ব্যবহারের btপরিবর্তে বিট-পরীক্ষা নির্দেশ 1ব্যবহার করবে test reg, imm32
পিটার কর্ডস

এই তাত্ক্ষণিক-ধ্রুব বিটম্যাপটি একটি বড় জয়, কারণ বিটম্যাপে কোনও ক্যাশে মিস নেই। "বিশেষ" ত্রুটি কোডগুলি সমস্ত 64 বা তারও কম পরিসরে থাকলে এটি কাজ করে। (অথবা 32 লিগ্যাসি 32 বিট কোডের জন্য।) সংকলকটি ক্ষুদ্রতম কেসের মান বাদ দেয়, যদি এটি শূন্য হয়। গ্রহণযোগ্যতাটি হ'ল সাম্প্রতিক সংকলকগুলি যথেষ্ট স্মার্ট যে আপনি সম্ভবত কোনও ভারী ডেটা কাঠামো ব্যবহার না করতে বললে আপনি যে কোনও যুক্তিই ব্যবহার করেন না কেন তা থেকে সম্ভবত আপনি ভাল কোড পাবেন।
পিটার কর্ডেস

24

সুইচ হয় দ্রুত।

একটি লুপের ভিতরে 30 / আলাদা-মানগুলি 30 /---র জন্য চেষ্টা করুন এবং স্যুইচটি কত গতিযুক্ত তা দেখতে সুইচ ব্যবহার করে এটি একই কোডের সাথে তুলনা করুন।

এখন, স্যুইচটিতে একটি আসল সমস্যা রয়েছে : প্রতিটি কেসের অভ্যন্তরের মানগুলি সংকলনের সময় স্যুইচটি অবশ্যই জানতে হবে। এর অর্থ নিম্নলিখিত কোড:

// WON'T COMPILE
extern const int MY_VALUE ;

void doSomething(const int p_iValue)
{
    switch(p_iValue)
    {
       case MY_VALUE : /* do something */ ; break ;
       default : /* do something else */ ; break ;
    }
}

সংকলন করবে না

তারপরে বেশিরভাগ লোকেরা সংজ্ঞায়িত (আরগ!) ব্যবহার করবে এবং অন্যরা একই সংকলনের ইউনিটে ধ্রুবক ভেরিয়েবলগুলি ঘোষণা এবং সংজ্ঞায়িত করবে। উদাহরণ স্বরূপ:

// WILL COMPILE
const int MY_VALUE = 25 ;

void doSomething(const int p_iValue)
{
    switch(p_iValue)
    {
       case MY_VALUE : /* do something */ ; break ;
       default : /* do something else */ ; break ;
    }
}

সুতরাং, শেষ পর্যন্ত, বিকাশকারীকে অবশ্যই "গতি + স্পষ্টতা" বনাম "কোড কাপলিং" এর মধ্যে চয়ন করতে হবে।

(এমন নয় যে একটি স্যুইচটি নরক হিসাবে বিভ্রান্তিকর হতে লেখা যায় না ... আমি বর্তমানে দেখি বেশিরভাগ স্যুইচটি এই "বিভ্রান্তিকর" বিভাগের ... তবে এটি অন্য গল্প ...)

2008-09-21 সম্পাদনা করুন:

bk1e নিম্নলিখিত মন্তব্যটি যুক্ত করেছে: " একটি হেডার ফাইলটিতে কনস্ট্যান্টগুলি সংজ্ঞায়িত করা এটি হ্যান্ডেল করার অন্য উপায় way"

অবশ্যই এটা.

বাহ্যিক ধরণের বিন্দুটি উত্স থেকে মানটি ডিকুয়াল করা ছিল। এই মানটিকে একটি ম্যাক্রো হিসাবে সাধারণ সংজ্ঞা হিসাবে ঘোষণা হিসাবে ঘোষণা করা, বা একটি এনাম হিসাবেও মানটি অন্তর্ভুক্ত করার পার্শ্ব-প্রতিক্রিয়া রয়েছে। সুতরাং, এনাম মান, বা কনট ইন্ট মান পরিবর্তন করা উচিত, একটি পুনঃসংশোধন প্রয়োজন হবে। বাহ্যিক ঘোষণার অর্থ মান পরিবর্তনের ক্ষেত্রে পুনরায় সংকলনের প্রয়োজন নেই, তবে অন্যদিকে, স্যুইচটি ব্যবহার করা অসম্ভব করে তোলে। স্যুইচ ব্যবহারের উপসংহারটি সুইচ কোড এবং কেস হিসাবে ব্যবহৃত ভেরিয়েবলগুলির মধ্যে সংযোগ বাড়িয়ে তুলবে । যখন এটি ঠিক আছে, তারপরে সুইচটি ব্যবহার করুন। যখন এটি না হয়, তখন অবাক হওয়ার কিছু নেই।

2013-01-15 সম্পাদনা করুন:

ভ্লাদ লাজারেনকো আমার উত্তর সম্পর্কে মন্তব্য করেছিলেন এবং একটি স্যুইচ দ্বারা উত্পন্ন সমাবেশের কোডটির তার গভীরতার সাথে অধ্যয়নের একটি লিঙ্ক দিয়েছিলেন। খুব আলোকিত: http://lazarenko.me/switch/


হেডার ফাইলটিতে কনস্ট্যান্টগুলি এনাম হিসাবে সংজ্ঞায়িত করা এটি হ্যান্ডেল করার অন্য উপায়।
bk1e

6
স্যুইচ সবসময় দ্রুত হয় না

1
@ ভ্লাদ লাজারেঙ্কো: লিঙ্কটির জন্য ধন্যবাদ! এটি একটি খুব আকর্ষণীয় পড়া ছিল।
প্যারাসেবল

1
@ আহমেদহসিন ব্যবহারকারী 404725 এর লিঙ্কটি মারা গেছে। ধন্যবাদ, আমি এটি ওয়েব্যাক মেশিনে পেয়েছি: web.archive.org/web/20131111091431/http://lazarenko.me/2013/01/… । আসলে, ওয়েব্যাক মেশিনটি যথেষ্ট আশীর্বাদ হতে পারে।
জ্যাক গিফিন

অনেক অনেক ধন্যবাদ, এটি খুব সহায়ক
আহমেদ হুসেন

20

সংকলক যেকোন উপায়ে এটি অপ্টিমাইজ করবে - এটি সর্বাধিক পঠনযোগ্য হিসাবে স্যুইচটিতে যান।


3
সম্ভাবনা হ'ল সংকলক যদি-তবে-পরে স্পর্শ করবে না। আসলে, gccনিশ্চিতভাবে এটি করবে না (এটির জন্য একটি ভাল কারণ আছে)। ঝনঝন উভয় ক্ষেত্রে বাইনারি অনুসন্ধানে অনুকূলিত করবে। উদাহরণস্বরূপ, দেখুন এই

7

স্যুইচ, যদি কেবল পঠনযোগ্যতার জন্য। জায়ান্ট যদি বিবৃতিগুলি বজায় রাখা শক্ত হয় এবং আমার মতে পড়া আরও শক্ত হয়।

ERROR_01 : // ইচ্ছাকৃত পতনের মাধ্যমে

অথবা

(ERROR_01 == numError) ||

পরেরটি আরও ত্রুটিযুক্ত প্রবণ এবং প্রথমটির চেয়ে বেশি টাইপিং এবং ফর্ম্যাটিংয়ের প্রয়োজন।


6

পাঠযোগ্যতার জন্য কোড। আপনি যদি আরও ভাল পারফর্ম করেন তা যদি জানতে চান তবে প্রোফাইলার ব্যবহার করুন, কেননা অপটিমাইজেশন এবং সংকলকগুলি পরিবর্তিত হয় এবং পারফরম্যান্সের সমস্যাগুলি খুব কমই যেখানে লোকেরা মনে করে তারা সেগুলি are


6

স্যুইচ ব্যবহার করুন, এটি এর জন্য এবং প্রোগ্রামাররা যা প্রত্যাশা করে।

আমি যদিও রিডানড্যান্ট কেস লেবেলগুলিতে রেখে দেব - কেবল লোককে স্বাচ্ছন্দ্য বোধ করার জন্য, আমি কখন / কী নিয়মগুলি এড়িয়ে চলেছে তা মনে করার চেষ্টা করছিলাম।
আপনি চান না যে পরবর্তী প্রোগ্রামার এতে কাজ করছে যাতে ভাষার বিবরণ সম্পর্কে কোনও অপ্রয়োজনীয় চিন্তাভাবনা করতে হয় (এটি কয়েক মাসের মধ্যে আপনিই হতে পারেন!)


4

সংকলকগুলি অনুকূলকরণে সত্যই ভাল switch। সাম্প্রতিক জিসিসি একটি শর্তের গুচ্ছটি অনুকূলকরণেও ভাল if

গডবোল্টে কিছু টেস্ট কেস করেছি

caseমানগুলি যখন একত্রে গোষ্ঠীভুক্ত হয়, তখন জিসিসি, ঝনঝন এবং আইসিসি সমস্ত বিটম্যাপ ব্যবহার করার জন্য যথেষ্ট স্মার্ট হয় যে কোনও মানটি বিশেষগুলির মধ্যে একটি কিনা তা পরীক্ষা করতে।

যেমন gcc 5.2 -O3 এর সাথে সংকলন করে switch(এবং ifখুব অনুরূপ কিছু):

errhandler_switch(errtype):  # gcc 5.2 -O3
    cmpl    $32, %edi
    ja  .L5
    movabsq $4301325442, %rax   # highest set bit is bit 32 (the 33rd bit)
    btq %rdi, %rax
    jc  .L10
.L5:
    rep ret
.L10:
    jmp fire_special_event()

লক্ষ্য করুন যে বিটম্যাপটি তাত্ক্ষণিক ডেটা, সুতরাং এতে কোনও সম্ভাব্য ডেটা-ক্যাশে মিস করা বা কোনও জাম্প টেবিল নেই।

gcc 4.9.2 -O3 switchবিটম্যাপে সংকলন করে , তবে মুভ 1U<<errNumber/ শিফট সহ করে। এটি ifশাখাগুলির সিরিজের সংস্করণটি সংকলন করে ।

errhandler_switch(errtype):  # gcc 4.9.2 -O3
    leal    -1(%rdi), %ecx
    cmpl    $31, %ecx    # cmpl $32, %edi  wouldn't have to wait an extra cycle for lea's output.
              # However, register read ports are limited on pre-SnB Intel
    ja  .L5
    movl    $1, %eax
    salq    %cl, %rax   # with -march=haswell, it will use BMI's shlx to avoid moving the shift count into ecx
    testl   $2150662721, %eax
    jne .L10
.L5:
    rep ret
.L10:
    jmp fire_special_event()

এটি কীভাবে 1 টি থেকে বিয়োগ করে errNumber( leaসেই পদক্ষেপের সাথে সেই ক্রিয়াকলাপটি একত্রিত করার জন্য) নোট করুন । এটি বিটম্যাপটিকে তাত্ক্ষণিক 32 বিটের মধ্যে ফিট করতে দেয় 64 64 বিট-তাত্ক্ষণিক এড়ানো movabsqযা আরও বেশি নির্দেশনা বাইট নেয়।

একটি সংক্ষিপ্ত (মেশিন কোডে) ক্রম হবে:

    cmpl    $32, %edi
    ja  .L5
    mov     $2150662721, %eax
    dec     %edi   # movabsq and btq is fewer instructions / fewer Intel uops, but this saves several bytes
    bt     %edi, %eax
    jc  fire_special_event
.L5:
    ret

(ব্যবহারে ব্যর্থতা jc fire_special_eventসর্বব্যাপী এবং এটি একটি সংকলক বাগ

rep retপুরানো এএমডি কে 8 এবং কে 10 (প্রাক-বুলডোজার) এর সুবিধার জন্য শাখা লক্ষ্যমাত্রা এবং নিম্নলিখিত শর্তাধীন শাখাগুলিতে ব্যবহৃত হয়: `rep ret` এর অর্থ কী? । এটি ছাড়া শাখার পূর্বাভাস সেই অপ্রচলিত সিপিইউগুলিতে তেমন কাজ করে না।

bt(বিট পরীক্ষা) একটি রেজিস্টার আর্গ সঙ্গে দ্রুত হয়। এটা তোলে দ্বারা একটি 1 বাম-নাড়াচাড়া কাজ সম্মিলন errNumberবিট এবং একটি করছেন test, কিন্তু এখনও 1 চক্র লেটেন্সি এবং শুধুমাত্র একটি একক ইন্টেল uop হয়। এটি মেমরি আর্গের সাথে ধীরে ধীরে সিআইএসসি শব্দার্থবিজ্ঞানের কারণে ধীরে ধীরে: "বিট স্ট্রিং" এর জন্য একটি মেমোরি অপারেন্ডের সাথে পরীক্ষা করতে হবে বাইটের ঠিকানাটি অন্য আর্গের ভিত্তিতে (8 দ্বারা বিভক্ত) গণনা করা হয়েছে, এবং 1, 2, 4, বা 8 বাইট অংশের মধ্যে সীমাবদ্ধ নয় স্মৃতি অপারেশন দ্বারা নির্দেশিত।

থেকে Agner কুয়াশা নির্দেশনা টেবিল , একটি পরিবর্তনশীল গোনা শিফট নির্দেশ কোন তুলনায় ধীর হয় btসাম্প্রতিক ইন্টেল (2 পরিবর্তে uops 1 এবং শিফট অন্য সব কিছুর যে প্রয়োজন করে না) করে।


4

অন্য কেসের ক্ষেত্রে সুইচ () এর সুবিধাগুলি: - ১. অন্য যেটির তুলনায় স্যুইচ অনেক বেশি কার্যকরী কারণ প্রতিটি ক্ষেত্রে পূর্ববর্তী মামলার উপর নির্ভর করে না অন্যথায় যেখানে পৃথক বিবৃতি সত্য বা মিথ্যা শর্তের জন্য পরীক্ষা করা দরকার।

  1. যখন একটি নেই। একক অভিব্যক্তির জন্য মানগুলির, সুইচ কেসের ক্ষেত্রে আরও নমনীয় কারণ অন্যথায় যদি মামলার রায় কেবল দুটি মানের উপর ভিত্তি করে হয় সত্য বা মিথ্যা হয়।

  2. স্যুইচ-এ মানগুলি ব্যবহারকারী সংজ্ঞায়িত করা হয়, তবে অন্য ক্ষেত্রে মানগুলি সীমাবদ্ধতার উপর ভিত্তি করে।

  3. ত্রুটির ক্ষেত্রে, স্যুইচ-এ থাকা বিবৃতিগুলি সহজেই ক্রস চেক এবং সংশোধন করা যেতে পারে যা অন্য বিবৃতি ক্ষেত্রে চেক করা তুলনামূলকভাবে কঠিন।

  4. স্যুইচ কেস আরও অনেক কমপ্যাক্ট এবং পড়তে এবং বুঝতে সহজ understand


2

আইএমও এটি কী স্যুইচ ফল-থ্রোয়ের জন্য তৈরি হয়েছিল তার একটি নিখুঁত উদাহরণ।


সি # তে এটিই একমাত্র ঘটনা যেখানে পতনের চিন্তাভাবনা ঘটে। ভাল তর্ক ঠিক আছে।
বিসিএস

2

যদি ভবিষ্যতে আপনার কেসগুলি গোষ্ঠীবদ্ধ হওয়ার সম্ভাবনা থাকে - যদি একের অধিক কেস এক ফলাফলের সাথে মিলে যায় - স্যুইচটি পড়া এবং বজায় রাখা সহজতর হতে পারে।


2

তারা সমানভাবে ভাল কাজ। একটি আধুনিক সংকলক প্রদত্ত পারফরম্যান্স প্রায় একই রকম।

কেস স্টেটমেন্টগুলির চেয়ে বিবৃতি যদি বেশি পঠনযোগ্য এবং আরও নমনীয় হয় তবে আমি পছন্দ করি - আপনি "|| সর্বোচ্চ <মিনিট" এর মতো সংখ্যার সমতার উপর ভিত্তি করে অন্যান্য শর্ত যুক্ত করতে পারেন। তবে আপনি এখানে যে সহজ সরল কেস পোস্ট করেছেন সেটির জন্য এটি সত্যিকার অর্থে কিছু যায় আসে না, কেবলমাত্র আপনার কাছে সবচেয়ে পাঠযোগ্য কি তা করুন।


2

স্যুইচটি অবশ্যই পছন্দসই। মামলাগুলির একটি স্যুইচের তালিকাটি দেখার পক্ষে সহজ এবং শর্তটি দীর্ঘ না পড়ার চেয়ে এটি কী করছে তা নিশ্চিতভাবে জানতে।

ifঅবস্থার সদৃশটি চোখের উপর শক্ত। ধরুন, এর মধ্যে একটি ==লেখা হয়েছিল !=; আপনি খেয়াল করবেন? অথবা যদি 'নম্বরেয়ার' এর একটি উদাহরণ 'এনএমইউরর' লেখা থাকে, যা কেবল সংকলনের জন্য ঘটেছে?

আমি সাধারণত স্যুইচের পরিবর্তে পলিমারফিজম ব্যবহার করতে পছন্দ করতাম তবে প্রসঙ্গের আরও বিশদ ছাড়াই এটি বলা শক্ত।

পারফরম্যান্স হিসাবে, আপনার সেরা বেট হ'ল আপনি বুনোতে প্রত্যাশা মতো একই পরিস্থিতিতে আপনার অ্যাপ্লিকেশনটির পারফরম্যান্স পরিমাপ করতে একটি প্রোফাইলার ব্যবহার করা। অন্যথায়, আপনি সম্ভবত ভুল জায়গায় এবং ভুল উপায়ে অপ্টিমাইজ করছেন।


2

আমি স্যুইচ সমাধানের সামঞ্জস্যের সাথে একমত তবে আপনি এখানে স্যুইচ হাইজ্যাক করছেন আইএমও ।
স্যুইচটির উদ্দেশ্যটি হ'ল মানের উপর নির্ভর করে বিভিন্ন হ্যান্ডলিং করা।
যদি আপনাকে সিডো কোডে আপনার অলগটি ব্যাখ্যা করতে হত তবে আপনি যদি একটি শব্দ ব্যবহার করেন তবে শব্দার্থকভাবে এটি হ'ল: যাইহোক_অরর যদি এটি করে ...
তবে যদি আপনি কোনও দিন কোনও ত্রুটির জন্য নির্দিষ্ট কোডের জন্য আপনার কোডটি পরিবর্তন করার পরিকল্পনা না করেন তবে আমি ব্যবহার করেন যদি


2
আমি একমত নই, একই কারণে আমি পতন-যদিও মামলার সাথে একমত নই। আমি "01,07,0A, 10,15,16 এবং 20 ফায়ার বিশেষ ইভেন্ট হিসাবে" হিসাবে স্যুইচটি পড়েছি। অন্য কোনও বিভাগে পতন-যদিও নেই।, এটি কেবলমাত্র C ++ সিনট্যাক্সের একটি নিদর্শন যেখানে আপনি প্রতিটি মানের জন্য 'কেস' কীওয়ার্ডটি পুনরাবৃত্তি করেন।
এমসাল্টারস

1

আমি স্পষ্টতা এবং সম্মেলনের স্বার্থে এই বিবৃতিটি বেছে নেব, যদিও আমি নিশ্চিত যে কেউ কেউ একমত হবে না। সর্বোপরি, আপনি কিছু করতে চাইছেন ifকিছু শর্ত সত্য! একটি ক্রিয়া সহ একটি স্যুইচ করা মনে হচ্ছে ... অল্পবিস্তর।


1

আমি সুইচ ব্যবহার করতে হবে। এইভাবে আপনাকে কেবল পৃথক পৃথক ফলাফলগুলি প্রয়োগ করতে হবে। আপনার দশটি অভিন্ন মামলা ডিফল্ট ব্যবহার করতে পারে। আপনার যে সমস্ত পরিবর্তন দরকার তা স্পষ্টভাবে পরিবর্তনটি প্রয়োগ করা উচিত, ডিফল্ট সম্পাদনা করার দরকার নেই। আইএফ এবং ইএলএসআইএফ সম্পাদনা করার চেয়ে সুইচ থেকে কেস যুক্ত করা বা অপসারণ করা আরও সহজ।

switch(numerror){
    ERROR_20 : { fire_special_event(); } break;
    default : { null; } break;
}

এমনকি আপনার অবস্থার (এই ক্ষেত্রে সংখ্যার ক্ষেত্রে) সম্ভাবনার তালিকার বিরুদ্ধে পরীক্ষা করুন, একটি অ্যারে সম্ভবত তাই আপনার সুইচ এমনকি ব্যবহার করা হয় না যদি না নিশ্চিতভাবেই ফলাফল হয় will


মোট প্রায় 30 টি ত্রুটি রয়েছে। 10 এর জন্য বিশেষ ক্রিয়া প্রয়োজন, সুতরাং আমি ~ 20 ত্রুটিগুলির জন্য ডিফল্টটি ব্যবহার করছি যাতে কোনও ক্রিয়া প্রয়োজন হয় না ...
জিং-

1

আপনার কাছে কেবল 30 টি ত্রুটি কোড রয়েছে, আপনার নিজের জাম্প টেবিলটি কোড করুন, তারপরে আপনি নিজেরাই সমস্ত অপ্টিমাইজেশন পছন্দগুলি করুন (জাম্পটি সর্বদা দ্রুততর হবে), পরিবর্তে সংকলকটি সঠিক কাজ করবে আশা করি। এটি কোডটিকে খুব ছোট করে তোলে (জাম্প টেবিলের স্থির ঘোষণা বাদে)। এটির পার্শ্ব সুবিধাটিও রয়েছে যে কোনও ডিবাগারের সাহায্যে রান টেক্সটে আপনার প্রয়োজন মতো আচরণটি সংশোধন করতে পারেন, কেবল টেবিলের ডেটা সরাসরি পোকার মাধ্যমে।


বাহ, এটি একটি সাধারণ সমস্যাটিকে জটিল অবস্থায় পরিণত করার উপায় বলে মনে হচ্ছে। কম্পাইলার আপনার জন্য দুর্দান্ত কাজ করবে কেন সেই সমস্ত সমস্যার দিকে যান। এছাড়াও এটি স্পষ্টতই একটি ত্রুটি পরিচালনাকারী, সুতরাং এটি এত দ্রুত সমালোচনামূলক হওয়ার সম্ভাবনা নেই। একটি স্যুইচ পড়া এবং রক্ষণাবেক্ষণের পক্ষে এখন পর্যন্ত সবচেয়ে সহজ জিনিস thing
মিঃজেব্রা

একটি সারণী খুব কমই জটিল - আসলে এটি কোডে স্যুইচ করার চেয়ে সম্ভবত সহজ। এবং বিবৃতিতে পারফরম্যান্সের বিষয়টি উল্লেখ করা হয়েছিল।
গ্রেগ হুইটফিল্ড

এটি অকাল অপটিমাইজেশনের মতো শোনাচ্ছে। যতক্ষণ আপনি আপনার এনাম মানগুলিকে ছোট এবং স্থিতিশীল রাখেন ততক্ষণ সংকলকটি এটি আপনার জন্য করা উচিত। আলাদা আলাদা ফাংশনে স্যুইচ লাগানো কোডটিকে সুন্দর এবং ছোট ব্যবহার করে রাখে, যেমন মার্ক র্যানসম তার উত্তরে বলেছিল, একই ক্ষুদ্র-কোড সুবিধা দেয়।
পিটার কর্ডেস

এছাড়াও, আপনি যদি নিজের কিছু বাস্তবায়ন করতে চলেছেন std::bitset<MAXERR> specialerror;তবে একটি তৈরি করুন if (specialerror[err]) { special_handler(); }। এটি জাম্প টেবিলের চেয়ে দ্রুত হবে, এসএসপি। না-নেওয়া ক্ষেত্রে।
পিটার কর্ডেস

1

আমি সেরা অনুশীলন সম্পর্কে নিশ্চিত নই, তবে আমি সুইচটি ব্যবহার করব - এবং তারপরে 'ডিফল্ট' মাধ্যমে ইচ্ছাকৃত পতনকে ফাঁদে ফেলব


1

নান্দনিকভাবে আমি এই পদ্ধতির পক্ষে যেতে চাই।

unsigned int special_events[] = {
    ERROR_01,
    ERROR_07,
    ERROR_0A,
    ERROR_10,
    ERROR_15,
    ERROR_16,
    ERROR_20
 };
 int special_events_length = sizeof (special_events) / sizeof (unsigned int);

 void process_event(unsigned int numError) {
     for (int i = 0; i < special_events_length; i++) {
         if (numError == special_events[i]) {
             fire_special_event();
             break;
          }
     }
  }

ডেটাটি আরও স্মার্ট করুন যাতে আমরা যুক্তিকে কিছুটা ঘন করতে পারি।

আমি বুঝতে পারি এটি অদ্ভুত দেখাচ্ছে। এখানে অনুপ্রেরণা রয়েছে (পাইথনে আমি এটি কীভাবে করব) থেকে:

special_events = [
    ERROR_01,
    ERROR_07,
    ERROR_0A,
    ERROR_10,
    ERROR_15,
    ERROR_16,
    ERROR_20,
    ]
def process_event(numError):
    if numError in special_events:
         fire_special_event()

4
একটি ল্যাঙ্গুয়েজ এর সিনট্যাক্স নেই কিভাবে আমরা একটি সমাধান বাস্তবায়ন উপর প্রভাব আছে ... => এটা কুশ্রী সি দেখায় এবং পাইথন মধ্যে সুন্দর। :)
rlerallut

বিটম্যাপ ব্যবহার করবেন? যদি ত্রুটি_এটি 0x0a ইত্যাদি হয় তবে আপনি সেগুলি দীর্ঘ দীর্ঘতে বিট হিসাবে রাখতে পারেন। দীর্ঘ দীর্ঘ বিশেষ_আভেন্টস = 1 এলএল << 1 | 1 এলএল << 7 | 1 এলএল << 0xa ... তারপরে ব্যবহার করুন (বিশেষ_আভেন্টস এবং (1 এলএল << numError) ফায়ার_স্পেশাল_আভেন্ট ()
পেপারহর্স

1
ইশ। আপনি একটি ও (1) সবচেয়ে খারাপ-অপারেশন (যদি জাম্প টেবিল তৈরি করা হয়) কে ও (এন) সবচেয়ে খারাপ ক্ষেত্রে পরিণত করেছেন (যেখানে এন কেস পরিচালিত হ'ল সংখ্যা) এবং আপনি breakবাইরের একটি case(হ্যাঁ, একটি নাবালক) ব্যবহার করেছেন পাপ, তবে একটি পাপ)। :)
ম্যাক

ইশ? তিনি বলেছিলেন পারফরম্যান্স এবং স্পেস সমালোচনা নয়। আমি কেবল সমস্যার দিকে তাকানোর আরও একটি উপায় প্রস্তাব করছিলাম। যদি আমরা এমন কোনও উপায়ে সমস্যার প্রতিনিধিত্ব করতে পারি যেখানে মানুষ কম চিন্তাভাবনা করে, তবে কম্পিউটারের আরও বেশি চিন্তাভাবনা করতে হবে তার অর্থ আমি সাধারণত যত্ন করে না।
mbac32768

1
while (true) != while (loop)

সম্ভবত প্রথমটি সংকলক দ্বারা অনুকূলিত হয়েছে, এটি ব্যাখ্যা করবে যে লুপের সংখ্যা বাড়ানোর সময় দ্বিতীয় লুপটি কেন ধীর হয়।


এটি ম্যাকনিক্সের উত্তরের মন্তব্য বলে মনে হচ্ছে। জাভাতে লুপ-এন্ড শর্ত হিসাবে ifবনাম টাইমিংয়ের সেই চেষ্টাতে এটিই সমস্যা switch
পিটার কর্ডেস

1

প্রোগ্রামটি সংকলন করার সময়, কোনও পার্থক্য আছে কিনা তা আমি জানি না। তবে প্রোগ্রামটি নিজেই এবং কোডটি যতটা সম্ভব সহজ রাখা, আমি ব্যক্তিগতভাবে মনে করি এটি আপনি কী করতে চান তার উপর নির্ভর করে। অন্যথায় যদি অন্য বিবৃতিগুলির সুবিধাগুলি থাকে, যা আমি মনে করি:

শর্তসাপেক্ষ হিসাবে আপনি ফাংশন (স্ট্যান্ডার্ড লাইব্রেরি বা ব্যক্তিগত) ব্যবহার করতে পারেন এমন নির্দিষ্ট রেঞ্জের বিপরীতে ভেরিয়েবল পরীক্ষা করার অনুমতি দেয়।

(উদাহরণ:

`int a;
 cout<<"enter value:\n";
 cin>>a;

 if( a > 0 && a < 5)
   {
     cout<<"a is between 0, 5\n";

   }else if(a > 5 && a < 10)

     cout<<"a is between 5,10\n";

   }else{

       "a is not an integer, or is not in range 0,10\n";

তবে অন্যথায় যদি তাড়াহুড়োয় বিবৃতিগুলি জটিল এবং অগোছালো হয়ে উঠতে পারে (আপনার সেরা চেষ্টা সত্ত্বেও)। স্যুইচ স্টেটমেন্টগুলি আরও পরিষ্কার, পরিষ্কার এবং সহজে পড়া সহজ হতে থাকে; তবে কেবলমাত্র নির্দিষ্ট মানগুলির বিরুদ্ধে পরীক্ষা করতে ব্যবহার করা যেতে পারে (উদাহরণ:

`int a;
 cout<<"enter value:\n";
 cin>>a;

 switch(a)
 {
    case 0:
    case 1:
    case 2: 
    case 3:
    case 4:
    case 5:
        cout<<"a is between 0,5 and equals: "<<a<<"\n";
        break;
    //other case statements
    default:
        cout<<"a is not between the range or is not a good value\n"
        break;

আমি যদি পছন্দ করি - অন্যথায় যদি - অন্য বিবৃতি দেয় তবে তা সত্যই আপনার উপর নির্ভর করে। আপনি যদি শর্ত হিসাবে ফাংশনগুলি ব্যবহার করতে চান, বা আপনি কোনও পরিসীমা, অ্যারে, বা ভেক্টর এবং / অথবা জটিল নীড়ের সাথে আচরণ করতে আপত্তি করেন না তবে আপনি যদি অন্য কিছু অবরুদ্ধ করেন তবে আমি ব্যবহার করার পরামর্শ দেব। আপনি যদি একক মানগুলির বিরুদ্ধে পরীক্ষা করতে চান বা আপনি একটি পরিষ্কার এবং সহজেই ব্লক পড়তে চান তবে আমি আপনাকে স্যুইচ () কেস ব্লক ব্যবহার করার পরামর্শ দিচ্ছি।


0

আমি সেই ব্যক্তি নই যা আপনাকে গতি এবং মেমরির ব্যবহার সম্পর্কে বলবে, তবে একটি স্যুইচ স্ট্যাচমেন্টের দিকে তাকাতে বোঝা অনেক সহজ জাহান্নাম তবে বড় যদি বিবৃতি হয় (বিশেষত ২-৩ মাস লাইনের নিচে)


0

আমি এর পুরানো জানি কিন্তু

public class SwitchTest {
static final int max = 100000;

public static void main(String[] args) {

int counter1 = 0;
long start1 = 0l;
long total1 = 0l;

int counter2 = 0;
long start2 = 0l;
long total2 = 0l;
boolean loop = true;

start1 = System.currentTimeMillis();
while (true) {
  if (counter1 == max) {
    break;
  } else {
    counter1++;
  }
}
total1 = System.currentTimeMillis() - start1;

start2 = System.currentTimeMillis();
while (loop) {
  switch (counter2) {
    case max:
      loop = false;
      break;
    default:
      counter2++;
  }
}
total2 = System.currentTimeMillis() - start2;

System.out.println("While if/else: " + total1 + "ms");
System.out.println("Switch: " + total2 + "ms");
System.out.println("Max Loops: " + max);

System.exit(0);
}
}

লুপের গণনা পরিবর্তনের ফলে অনেক পরিবর্তন হয়:

যখন / অন্য: 5 এমএস স্যুইচ করুন: 1 মিমি সর্বোচ্চ লুপগুলি: 100000

যখন / অন্য: 5 মিমি স্যুইচ করুন: 3 মিমি সর্বোচ্চ লুপগুলি: 1000000

যখন / অন্যথায়: 5 মিমি স্যুইচ করুন: 14 মিমি সর্বোচ্চ লুপগুলি: 10000000 00

যখন / অন্যথায়: 5 মিমি স্যুইচ করুন: 149 মিমি সর্বোচ্চ লুপগুলি: 100000000

(আপনি চাইলে আরও বিবৃতি যুক্ত করুন)


3
ভাল কথা, তবে শ্রুতি, বন্ধু, আপনি ভুল ভাষায় আছেন। ভাষার পরিবর্তিতকরণে অনেক পরিবর্তন হয়;)
গ্যাব্রিয়েল শ্রায়বার

2
if(max) breakলুপ লুপ গণনা নির্বিশেষে ধ্রুব সময় চালায়? JIT- সংকলক মত শব্দ লুপ দূরে অপ্টিমাইজ করতে যথেষ্ট স্মার্ট counter2=max। এবং সম্ভবত এটি প্রথমে কলটির currentTimeMillisওভারহেড বেশি থাকলে এটি স্যুইচের চেয়ে ধীর গতির কারণ, এখনও সবকিছু জেআইটি-সংকলিত নয়? লুপগুলি অন্য ক্রমে রেখে দেওয়া সম্ভবত বিভিন্ন ফলাফল দেয়।
পিটার কর্ডেস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.