তুচ্ছ-শর্তযুক্ত শর্তাধীন বিবৃতিগুলি কি লুপের সূচনা বিভাগে স্থানান্তরিত করা উচিত?


21

এই প্রশ্নটি আমি স্ট্যাকওভারফ্লো ডটকম এ পেয়েছি

নিম্নলিখিত প্যাটার্নটি সাধারণ:

final x = 10;//whatever constant value
for(int i = 0; i < Math.floor(Math.sqrt(x)) + 1; i++) {
  //...do something
}

আমি যে বিষয়টিটি তৈরির চেষ্টা করছি তা হ'ল শর্তাধীন বিবৃতিটি জটিল কিছু এবং পরিবর্তিত হয় না।

লুপের প্রারম্ভিককরণ বিভাগে এটি ঘোষণা করা আরও ভাল কি?

final x = 10;//whatever constant value
for(int i = 0, j = Math.floor(Math.sqrt(x)) + 1; i < j; i++) {
  //...do something
}

এটা কি আরও পরিষ্কার?

শর্তসাপেক্ষ মত প্রকাশের মত যদি সহজ হয়

final x = 10;//whatever constant value
for(int i = 0, j = n*n; i > j; j++) {
  //...do something
}

47
লুপের আগে কেন কেবল এটিকে লাইনে স্থানান্তরিত করবেন না , তবে আপনি এটি একটি বুদ্ধিমান নামও দিতে পারেন।
jonrsharpe

2
@ মেহরদাদ: তারা সমতুল্য নয়। যদি xআকারে বড় হয় Math.floor(Math.sqrt(x))+1তবে সমান Math.floor(Math.sqrt(x))। :-)
আর ..

5
@ জোনারশপে কারণ এটি ভেরিয়েবলের পরিধি আরও প্রশস্ত করবে। আমি অগত্যা বলছি না যে এটি না করার একটি ভাল কারণ, তবে এটি কারণ কিছু লোক না করে।
কেভিন ক্রামউইদে

3
@ কেভিনক্রামউইদে যদি সুযোগটি কোনও উদ্বেগের সীমা থাকে তবে কোডটি নিজের ব্লকে রেখে, যেমন, { x=whatever; for (...) {...} }বা আরও ভাল, বিবেচনা করুন যে এটির একটি পৃথক ফাংশন হওয়া দরকার কিনা যথেষ্ট।
blrfl

2
@ জোনারশপে এটিকে ডিআইপি বিভাগেও ঘোষণা করার সময় আপনি এটি একটি বুদ্ধিমান নাম দিতে পারেন। বলছি না যে আমি এটি সেখানে রাখব; এটি পৃথক হলে এটি পড়া এখনও সহজ।
জলিজোকার

উত্তর:


62

আমি যা করব তা হ'ল এই জাতীয় কিছু:

void doSomeThings() {
    final x = 10;//whatever constant value
    final limit = Math.floor(Math.sqrt(x)) + 1;
    for(int i = 0; i < limit; i++) {
         //...do something
    }
}

সত্যই লুপ শিরোনামে j(এখন limit) আরম্ভ করার একমাত্র ভাল কারণ হ'ল এটি সঠিকভাবে বাদ দেওয়া। একটি নন ইস্যুটি একটি দুর্দান্ত টাইট এনকোলেজিং সুযোগ হ'ল এটি তৈরিতে যা লাগে তা।

আমি দ্রুত হওয়ার আকাঙ্ক্ষার প্রশংসা করতে পারি তবে সত্যিকারের কোনও ভাল কারণ ছাড়াই পাঠযোগ্যতার ত্যাগ করতে পারি না।

অবশ্যই, সংকলকটি অনুকূলিত করতে পারে, একাধিক ভারের সূচনা বৈধ হতে পারে তবে লুপগুলি ডিবাগ করার মতো যথেষ্ট শক্ত। দয়া করে মানুষের প্রতি দয়া করুন। যদি এটি সত্যিই আমাদের মন্থর করে তুলতে পারে তবে এটিকে ঠিক করার পক্ষে এটি যথেষ্ট ভাল nice


ভাল যুক্তি. আমি ধরে নিতে পারি যদি অন্য কিছু পরিবর্তনশীল নিয়ে বিরক্ত না হয় তবে অভিব্যক্তিটি যদি কিছু সাধারণ হয় তবে উদাহরণস্বরূপ for(int i = 0; i < n*n; i++){...}আপনি n*nকোনও ভেরিয়েবলকে বরাদ্দ করবেন না ?
সেলিব্রিটিস

1
আমি এবং আমার আছে। তবে গতির জন্য নয়। পাঠযোগ্যতার জন্য। পঠনযোগ্য কোডটি নিজে থেকে দ্রুত হতে থাকে।
candied_orange

1
এমনকি যদি আপনি চিহ্নিত করে ধ্রুবক হিসাবে ( final) হিসাবে চিহ্নিত করা থাকে তবে এটি স্কোপ করার বিষয়টিও চলে যায় । সংকলক প্রয়োগকারী এটি পরিবর্তন থেকে রোধ করে এমন ধ্রুবকটি যদি কার্যক্রমে পরে অ্যাক্সেসযোগ্য হয় তবে কে চিন্তা করে?
jpmc26

আমি মনে করি একটি বড় বিষয় হ'ল যা আপনি প্রত্যাশা করেন। আমি জানি উদাহরণটি স্কয়ারটি ব্যবহার করে তবে এটি যদি অন্য ফাংশন হয়? কাজটি কি খাঁটি? আপনি কি সবসময় একই মান আশা করছেন? পার্শ্ব প্রতিক্রিয়া আছে? পার্শ্ব প্রতিক্রিয়া কি আপনি প্রতিটি পুনরাবৃত্তি উপর ঘটতে চান কিছু প্রভাব?
পিটার বি

38

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

যাহোক...

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

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


5
একবার আপনি ফাংশন কলগুলি অন্তর্ভুক্ত করা শুরু করলে এটি সংকলকটির অনুকূলিতকরণের জন্য আরও শক্ত হয়ে যায়। সংকলকটির বিশেষ জ্ঞান থাকতে হবে যে ম্যাথ.এসকিআর্টির কোনও পার্শ্ব প্রতিক্রিয়া নেই।
পিটার গ্রিন

@ পিটারগ্রিন যদি এটি জাভা হয় তবে জেভিএম এটি সনাক্ত করতে পারে তবে এতে কিছুটা সময় লাগতে পারে।
ক্রাইলিস-হরতাল-

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

ম্যাড.সেকআরটি (এক্স) মাইমডিউল দ্বারা প্রতিস্থাপন করা হলে এটি আকর্ষণীয় হয়ে ওঠে omeসুমননপিউরমেথোডভিথসাইডএফেক্টস (এক্স)।
পিটার বি

9

@ কার্ল বিলেফেল্ট তার উত্তরে যেমন বলেছেন, এটি সাধারণত একটি নন-ইস্যু।

তবে এটি এক সময় সি এবং সি ++ এ একটি সাধারণ সমস্যা ছিল এবং কোডটি পঠনযোগ্যতাটি হ্রাস না করে ইস্যুটি পাশের দিকে, নীচে টেনে নিয়ে যাওয়া একটি কৌশল ছিল0

final x = 10;//whatever constant value
for(int i = Math.floor(Math.sqrt(x)); i >= 0; i--) {
  //...do something
}

এখন প্রতিটি পুনরাবৃত্তির শর্তসাপেক্ষ কেবল >= 0প্রতিটি সংকলক 1 বা 2 বিধানসভা নির্দেশগুলিতে সংকলন করবে। গত কয়েক দশকে প্রতিটি সিপিইউতে এই জাতীয় প্রাথমিক পরীক্ষা করা উচিত; আমার এক্স 64 মেশিনে একটি চেক চেক করে আমি দেখতে পাচ্ছি যে এটি পূর্বাবস্থায় রূপান্তরিত হয় cmpl $0x0, -0x14(%rbp)(লং- ইন -তুলনা মান 0 বনাম রেজিস্টার আরবিপি অফসেটেড -14) এবং jl 0x100000f59(পূর্ববর্তী তুলনাটি "২ য়-আর্গের জন্য সত্য হলে লুপের অনুসরণের নির্দেশে ঝাঁপ দাও" <ম-আর্গ ")

মনে রাখবেন যে আমি + 1এখান থেকে সরিয়েছি Math.floor(Math.sqrt(x)) + 1; গণিতে কাজ করার জন্য, প্রারম্ভিক মান হওয়া উচিত int i = «iterationCount» - 1। এছাড়াও লক্ষণীয় যে আপনার পুনরুক্তি সাইন ইন করা আবশ্যক; unsigned intকাজ করবে না এবং সম্ভবত সংকলক-সতর্ক করবে।

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


1
আপনার লেখার সমস্ত কিছুই প্রযুক্তিগতভাবে সঠিক। নির্দেশাবলী সম্পর্কে মন্তব্য যদিও বিভ্রান্তিকর হতে পারে, যেহেতু সমস্ত আধুনিক সিপিইউগুলি তাদের জন্য বিশেষ নির্দেশনা আছে কিনা তা বিবেচনা না করে ফরোয়ার্ড পুনরাবৃত্তি লুপগুলি নিয়ে ভালভাবে কাজ করার জন্য ডিজাইন করা হয়েছে। যে কোনও ক্ষেত্রে, বেশিরভাগ সময় সাধারণত লুপের অভ্যন্তরে ব্যয় হয়, পুনরাবৃত্তি না করে।
জর্জেন ফোগ

4
এটি লক্ষ করা উচিত যে আধুনিক সংকলক অপ্টিমাইজেশানগুলি "সাধারণ" কোডটি মাথায় রেখে ডিজাইন করা হয়েছে। বেশিরভাগ ক্ষেত্রেই, সংকলকটি কোড উত্পন্ন করবে যা আপনি অপ্টিমাইজেশন "ট্রিকস" ব্যবহার করেন কিনা তা নির্বিশেষে তত দ্রুত code তবে কিছু কৌশল আসলে কীভাবে জটিল তার উপর নির্ভর করে অপ্টিমাইজেশনে বাধা দিতে পারে । নির্দিষ্ট কৌশলগুলি ব্যবহার করা যদি আপনার কোডটিকে আরও পঠনযোগ্য করে তোলে বা সাধারণ বাগগুলি ধরতে সহায়তা করে তবে দুর্দান্ত great তবে নিজেকে এই ভেবে ভ্রান্ত করবেন না "যদি আমি এইভাবে কোড লিখি তবে এটি আরও দ্রুত হবে" " আপনি কীভাবে সাধারণত কোড লিখবেন, তারপরে আপনাকে অনুকূলকরণের প্রয়োজন এমন স্থানগুলি অনুসন্ধান করার জন্য প্রোফাইল profile
0x5453

এছাড়াও মনে রাখবেন যে unsignedআপনি যদি চেকটি পরিবর্তন করেন তবে কাউন্টারগুলি এখানে কাজ করবে (সবচেয়ে সহজ উপায় হ'ল উভয় পক্ষের একই মান যুক্ত করা); উদাহরণস্বরূপ, কোনো হ্রাস জন্য Dec, চেক (i + Dec) >= Decসবসময় একই ফলে থাকা উচিত signedচেক i >= 0, উভয় সঙ্গে signedএবং unsignedকাউন্টার, যতদিন ভাষার জন্য ভালভাবে সংজ্ঞায়িত Wraparound নিয়ম আছে unsignedভেরিয়েবল (বিশেষত -n + n == 0উভয়ের জন্য সত্য হতে হয়েছে signedএবং unsigned)। মনে রাখবেন, তবে এটি স্বাক্ষরিত >=0চেকের চেয়ে কম দক্ষ হতে পারে , যদি সংকলকটির এটির জন্য কোনও অপ্টিমাইজেশন না থাকে।
জাস্টিন সময় - মনিকা

1
@ জাস্টিনটাইম হ্যাঁ, স্বাক্ষরিত প্রয়োজনটি সবচেয়ে শক্ততম অংশ; একটি যোগ Decউভয় শুরু মান ধ্রুবক এবং মান কাজ শেষ কিন্তু এটা অনেক কম স্বজ্ঞাত তোলে, এবং ব্যবহার করা হয় তবে iতারপর একটি অ্যারের সূচক হিসাবে আপনি একটি যা করতে হবে চাই unsigned int arrayI = i - Dec;লুপ শরীরের। স্বাক্ষরবিহীন পুনরাবৃত্তকারীটির সাথে আটকে গেলে আমি কেবলমাত্র সামনের-পুনরাবৃত্তি ব্যবহার করি; i <= count - 1বিপরীত-পুনরাবৃত্তি লুপগুলির লজিককে সমান্তরাল রাখতে প্রায়শ শর্তাধীন থাকে।
স্লিপ ডি থম্পসন

1
@ স্লিপডি.টম্পসনের অর্থ আমি বিশেষত Decশুরু এবং শেষের মানগুলিকে যুক্ত করতে চাই নি , তবে শর্তটি Decউভয় পক্ষের দিকে সরিয়ে নিয়ে যাওয়া চাই। for (unsigned i = N - 1; i + 1 >= 1; i--) /*...*/ এটি আপনাকে iলুপের মধ্যে সাধারণত ব্যবহার করতে দেয় , যখন গ্যারান্টি দেয় যে শর্তের বাম দিকে সর্বনিম্ন সম্ভাব্য মান হ'ল 0(মোড়কে হস্তক্ষেপ থেকে রেফারাউন্ড প্রতিরোধ করা)। এটা স্পষ্টভাবে অনেক বেশি সহজ যখন স্বাক্ষরবিহীন কাউন্টারে সঙ্গে কাজ এগিয়ে পুনরাবৃত্তির ব্যবহার করার যদিও।
জাস্টিন সময় -

3

ম্যাড.সেকআরটি (এক্স) মাইমডিউল দ্বারা প্রতিস্থাপন করা হলে এটি আকর্ষণীয় হয়ে ওঠে omeসুমননপিউরমেথোডভিথসাইডএফেক্টস (এক্স)।

মূলত আমার মোডাস অপারেন্ডিটি হ'ল: যদি কোনও কিছু সর্বদা একই মান হিসাবে প্রত্যাশিত হয় তবে কেবল একবার এটি মূল্যায়ন করুন। উদাহরণস্বরূপ তালিকা.কাউন্ট, যদি লুপটির ক্রিয়াকলাপের সময় তালিকাটি পরিবর্তন না হয় বলে মনে করা হয়, তবে লুপের বাইরে গণনাটি অন্য ভেরিয়েবলে নিয়ে যান।

এই "গণনা "গুলির কয়েকটি বিস্ময়করভাবে ব্যয়বহুল হতে পারে বিশেষত যখন আপনি ডেটাবেসগুলি নিয়ে কাজ করছেন। এমনকি যদি আপনি এমন কোনও ডেটাসেটে কাজ করছেন যা তালিকার পুনরাবৃত্তির সময় পরিবর্তন হওয়ার কথা নয়।


যখন গণনা ব্যয়বহুল হয়, আপনার এটিকে মোটেই ব্যবহার করা উচিত নয়। পরিবর্তে আপনার সমতাটি করা উচিতfor( auto it = begin(dataset); !at_end(it); ++it )
বেন ভয়েগট

@ বেনভয়েগট এই অপারেশনগুলির জন্য অবশ্যই একটি পুনরুক্তি ব্যবহারকারক অবশ্যই সেরা উপায় side আমি পার্শ্ব-প্রতিক্রিয়া সহ অ-খাঁটি পদ্ধতি ব্যবহারের বিষয়ে আমার বক্তব্যটি বর্ণনা করার জন্য কেবল এটি উল্লেখ করেছি।
পিটার বি

0

আমার মতে এটি অত্যন্ত ভাষা নির্দিষ্ট। উদাহরণস্বরূপ, সি ++ 11 ব্যবহার করা হলে আমি সন্দেহ করব যে শর্তটি পরীক্ষা করা যদি একটি constexprফাংশন হয় তবে কম্পাইলার একাধিক মৃত্যুদন্ড কার্যকর করতে খুব সম্ভবত সম্ভাবনাযুক্ত কারণ এটি জানে যে এটি প্রতিবার একই মান অর্জন করবে।

তবে যদি ফাংশন কলটি একটি লাইব্রেরি ফাংশন হয় যা constexprসংকলক নয় এটি অবশ্যই অবশ্যই প্রতিটি পুনরাবৃত্তির উপর এটি চালিত করতে চলেছে কারণ এটি এটিকে হ্রাস করতে পারে না (যদি না এটি ইনলাইন থাকে এবং তাই খাঁটি হিসাবে কেটে নেওয়া যায়)।

আমি জাভা সম্পর্কে কম জানি কিন্তু প্রদত্ত জেআইটি সংকলিত আমি অনুমান করব যে সংকলকটিতে রানটাইমের সময় সম্ভাব্য ইনলাইন এবং শর্তটি অপ্টিমাইজ করার জন্য পর্যাপ্ত তথ্য রয়েছে। তবে এটি ভাল সংকলক ডিজাইনের উপর নির্ভর করবে এবং এই লুপটি স্থির করে সংকলকটি একটি অপ্টিমাইজেশন অগ্রাধিকার ছিল যা আমরা কেবল অনুমান করতে পারি।

ব্যক্তিগতভাবে আমি অনুভব করি যে আপনি যদি পারেন তবে লুপটির মধ্যে শর্তটি রাখা আরও সামান্য মার্জিত, তবে এটি জটিল হলে আমি এটি একটি constexprবা inlineফাংশনে লিখব , বা আপনার ভাষাগুলি ইঙ্গিত করার সমতুল্য যে ফাংশনটি খাঁটি এবং আশাবাদী। এটি অভিপ্রায়টিকে সুস্পষ্ট করে তোলে এবং একটি বিশাল অপঠনযোগ্য লাইন তৈরি না করে আইডিয়োম্যাটিক লুপ স্টাইলটি বজায় রাখে। এটি শর্তটি একটি নিজস্ব ফাংশন হলে এটির একটি নাম দেয় যাতে পাঠকরা তাত্ক্ষণিকভাবে জটিলটি পড়তে না পারলে চেকটি কী তা জন্য যুক্তিযুক্তভাবে দেখতে পারেন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.