আপাতদৃষ্টিতে অন্তহীন লুপটি শেষ হয়ে যায়, যদি না System.out.println ব্যবহার করা হয়


91

আমার কাছে একটি সহজ বিট কোড ছিল যা অনন্ত লুপ হওয়ার কথা ছিল যেহেতু xসর্বদা বৃদ্ধি পাবে এবং সর্বদা এর চেয়ে বড় থাকবে j

int x = 5;
int y = 9;
for (int j = 0; j < x; j++) {
   x = x + y;
}
System.out.println(y);

তবে যেমন রয়েছে, এটি প্রিন্ট করে yএবং অবিরাম লুপ করে না। আমি কেন চিন্তা করতে পারে না. যাইহোক, আমি যখন নিম্নলিখিত পদ্ধতিতে কোডটি সামঞ্জস্য করি:

int x = 5;
int y = 9;
for (int j = 0; j < x; j++) {
    x = x + y;
    System.out.println(y);
}
System.out.println(y);

এটি একটি অন্তহীন লুপ হয়ে যায় এবং কেন আমি জানি না। জাভা কি এটির একটি অন্তহীন লুপটি সনাক্ত করে এবং প্রথম পরিস্থিতিতে এড়িয়ে যায় তবে দ্বিতীয়টিতে একটি পদ্ধতি কল কার্যকর করতে হবে যাতে এটি প্রত্যাশার সাথে আচরণ করে? বিভ্রান্ত :)


4
দ্বিতীয় লুপটি সীমাহীন কারণ লুপ ভেরিয়েবলের চেয়ে উপরের xসীমাটি দ্রুত বৃদ্ধি পায় j। অন্য কথায় jকখনই উপরের বাউন্ডে আঘাত করবে না, তাই লুপটি "চিরকাল" চলবে। ঠিক আছে, চিরকালের জন্য নয়, আপনি সম্ভবত কোনও সময়ে একটি ওভারফ্লো পাবেন।
টিম বিগলেসেইন

75
এটি একটি অন্তহীন লুপ নয়, কেবলমাত্র প্রথম ক্ষেত্রে লুপ থেকে বেরিয়ে আসতে 238609294 বার লাগে এবং দ্বিতীয়বার এটি y238609294 বারের মূল্য মুদ্রণ করে
N00b Pr0grammer

13
একটি শব্দের উত্তর: উপচে পড়া
qwr

20
মজাদারভাবে, শেষের System.out.println(x)পরিবর্তে yতাত্ক্ষণিকভাবে সমস্যাটি কী তা দেখিয়ে
দিত

9
পছন্দ করুন আপনার যদি প্রকারের টাইপ সম্পর্কে সন্দেহ থাকে তবে জাভা ভাষার স্পেসটি পড়ুন। এটি হার্ডওয়্যার ইন্ডিপেন্ডেন্ট।
9 বিএসডিএক্স 9 আরভিজে 0lo

উত্তর:


161

উদাহরণ দুটিই অন্তহীন নয়।

সমস্যাটি intজাভা (বা অন্য কোনও সাধারণ ভাষায়) প্রকারের সীমাবদ্ধতা । যখন xপৌঁছানোর মান হয় 0x7fffffff, কোনও ধনাত্মক মান যুক্ত করলে ওভারফ্লো হয় এবং xনেতিবাচক হয়ে যায়, সুতরাং এর চেয়ে কম j

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

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


48
আমি কেবলমাত্র একটি প্রোগ্রাম চেষ্টা করেছি (আমার ল্যাপটপে) যা লুপটিতে একটি লাইন প্রিন্ট করে। আমি এটি টাইম করেছি এবং এটি প্রায় 1000 লাইন / সেকেন্ড মুদ্রণ করতে সক্ষম হয়েছিল। N00b এর মন্তব্যের ভিত্তিতে যে লুপটি 238609294 বার কার্যকর করবে, লুপটি শেষ হতে প্রায় 23861 সেকেন্ড সময় লাগবে - 6.6 ঘন্টােরও বেশি। "কয়েক মিনিট" এর চেয়ে বেশি বাচ্চা।
এজেবি

11
@ এজেবি: বাস্তবায়নের উপর নির্ভর করে। println()উইন্ডোজ আইআইআরসি হ'ল একটি ব্লকিং অপারেশন, যেখানে (কিছু?) ইউনিক্সে এটি বাফার হয়েছে তাই খুব দ্রুত চলে। এছাড়াও ব্যবহার করার চেষ্টা করুন print(), যা বাফার পর্যন্ত এটি একটি হিট \n(অথবা বাফার ভর্তি, অথবা flush()বলা হয়)
ড্যানি Pflughoeft - BlueRaja

6
এছাড়াও এটি আউটপুটটি দেখায় টার্মিনালের উপর নির্ভর করে। চূড়ান্ত উদাহরণের জন্য স্ট্যাকওভারফ্লো.com/a/21947627/53897 দেখুন (যেখানে শব্দ মোড়ানোর কারণে ধীর গতি হচ্ছিল)
থরবজরন রাভন অ্যান্ডারসেন

4
হ্যাঁ, এটি ইউনিক্সে বাফার হয়েছে তবে এটি এখনও অবরুদ্ধ। 8K বা এর বেশি বাফার একবার পূরণ করলে এটি জায়গা না পাওয়া অবরুদ্ধ হয়ে যাবে। গতিটি কত তাড়াতাড়ি গ্রাস করবে তার উপর নির্ভর করবে। আউটপুটটিকে / dev / null এ পুনঃনির্দেশ করা দ্রুত হবে তবে এটি টার্মিনালে পাঠানো হলে ডিফল্টরূপে স্ক্রিনে গ্রাফিক্স আপডেট এবং আরও ফাংশনগুলি কমিয়ে দেওয়ার প্রয়োজন হবে কারণ এটি ফন্টগুলি ধীর করে দেয়।
পেঙ্গুইন 359

4
@ জবনেেক ওহ, সম্ভবত তাই, তবে এটি আমাকে মনে করিয়ে দেয়, টার্মিনালগুলি I / O সাধারণত লাইন বাফার হতে চলেছে, ব্লক করে না সম্ভবত প্রতিটি প্রিন্টলন সিস্টেম কলের ফলে টার্মিনাল কেসটিকে আরও ধীর করে দেয়।
পেঙ্গুইন 359

33

যেহেতু এগুলি int হিসাবে ঘোষিত হয়, একবার এটি সর্বোচ্চ মান পর্যন্ত পৌঁছে যায়, এক্স মানটি নেতিবাচক হয়ে যাওয়ার সাথে সাথে লুপটি ভেঙে যায়।

কিন্তু যখন System.out.println লুপটিতে যুক্ত করা হয় তখন সম্পাদনের গতি দৃশ্যমান হয় (কনসোল আউটপুট আউটাইজেশন গতি কমিয়ে দেয়)। তবে, যদি আপনি ২ য় প্রোগ্রামটি (লুপের ভিতরে সিসো সহ একটি) বেশিক্ষণ চলতে দেন তবে এটির প্রথমটির মতো (লুপের ভিতরে সিসোবিহীন একটি) আচরণ করা উচিত।


21
লোকেরা বুঝতে পারে না যে কনসোলে কত স্প্যামিং করা তাদের কোডটি ধীর করতে পারে।
ব্যবহারকারী 9993

13

এর দুটি কারণ থাকতে পারে:

  1. জাভা forলুপটি অনুকূল করে এবং যেহেতু লুপের xপরে কোনও ব্যবহার নেই , কেবল লুপটি সরিয়ে দেয়। আপনি System.out.println(x);লুপ পরে স্টেটমেন্ট লাগিয়ে এটি পরীক্ষা করতে পারেন ।

  2. এটি সম্ভবত জাভা আসলে লুপটিকে অনুকূল করে নিচ্ছে না এবং এটি প্রোগ্রামটি সঠিকভাবে সম্পাদন করছে এবং অবশেষে xখুব বেশি বড় হবে intএবং উপচে পড়বে । পূর্ণসংখ্যা ওভারফ্লো সম্ভবত সংখ্যাকে xনেতিবাচক হিসাবে তৈরি করবে যা জ এর চেয়ে ছোট হবে এবং এটি লুপ থেকে বেরিয়ে এসে এর মান মুদ্রণ করবে y। এটি System.out.println(x);লুপের পরে যুক্ত করেও পরীক্ষা করা যায় ।

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


14
আমি দরজা সংখ্যা 2. চয়ন
Robby Cornelissen

সত্য। এটি নেতিবাচক স্কেলে গিয়ে লুপটি প্রস্থান করে। তবে একটি sysoutঅসীম লুপের একটি বিভ্রম যোগ করতে এত ধীর।
পবন কুমার

4
1. একটি বাগ হতে হবে। সংকলক অপ্টিমাইজেশন একটি প্রোগ্রামের আচরণ পরিবর্তন করার অনুমতি দেওয়া হয় না। যদি এটি অসীম লুপ হয়, তবে সংকলকটি যা যা চায় তার সবথেকে অনুকূল করতে পারে, তবে ফলাফলটি এখনও একটি অসীম লুপ হতে পারে। আসল সমাধানটি হ'ল ওপিকে ভুল করা হয়েছে: দুজনের কোনওটিই অসীম লুপ নয়, একজন কেবল অন্যটির চেয়ে বেশি কাজ করে, তাই এটি বেশি সময় নেয়।
জার্গ ডব্লু মিট্টাগ

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

1

এগুলি উভয়ই অন্তহীন লুপ নয়, প্রাথমিকভাবে j = 0, যতক্ষণ না জ <x, জে বৃদ্ধি পায় (জে ++), এবং জ একটি পূর্ণসংখ্যা তাই লুপটি সর্বোচ্চ মান পর্যন্ত না পৌঁছা পর্যন্ত চলবে (একটি পূর্ণসংখ্যা ওভারফ্লো শর্ত এটি তখন ঘটে যখন গুণাগুণের অপারেশনের ফলাফল, যেমন গুণ বা সংযোজন, এটি সংরক্ষণের জন্য ব্যবহৃত পূর্ণসংখ্যার ধরণের সর্বাধিক আকার ছাড়িয়ে যায়))। দ্বিতীয় উদাহরণের জন্য লুপটি বিরতি না হওয়া পর্যন্ত সিস্টেমটি কেবল y এর মান মুদ্রণ করে।

যদি আপনি একটি অন্তহীন লুপের উদাহরণ সন্ধান করেন তবে এটির মতো দেখতে হবে

int x = 6;

for (int i = 0; x < 10; i++) {
System.out.println("Still Looping");
}

কারণ (এক্স) কখনই 10 এর মান অর্জন করতে পারে না;

আপনি লুপের জন্য ডাবল সহ একটি অসীম লুপ তৈরি করতে পারেন:

int i ;

  for (i = 0; i <= 10; i++) {
      for (i = 0; i <= 5; i++){
         System.out.println("Repeat");   
      }
 }

এই লুপটি অসীম কারণ লুপের জন্য প্রথম বলে i <10, যা সত্য তাই এটি লুপের জন্য দ্বিতীয়টিতে যায় এবং দ্বিতীয়টি লুপের জন্য (i) এর মান বৃদ্ধি করে যতক্ষণ না এটি == 5 হয় তবে এটি প্রথমটিতে চলে যায় আবার লুপের জন্য কারণ আমি <10, প্রক্রিয়াটি পুনরাবৃত্তি করে কারণ এটি লুপের জন্য দ্বিতীয়টির পরে পুনরায় সেট হয়


1

এটি একটি সীমাবদ্ধ লুপ কারণ আপনি একবার মুদ্রণ করুন বা না থাকুক, একবার মানটি (যা xএকটিটির 2,147,483,647সর্বোচ্চ মান int) ছাড়িয়ে যায় , xনেতিবাচক হয়ে উঠবে এবং কোনওটির চেয়ে jবেশি হবে না।

আপনি কেবলমাত্র এর মানটি পরিবর্তন yকরতে 100000এবং লুপটিতে মুদ্রণ করতে পারেন এবং yলুপটি খুব শীঘ্রই ভেঙে যাবে।

যে কারণে আপনি এটিকে অসীম বলে মনে করছেন তা হ'ল System.out.println(y);কোডটি কোনও ক্রিয়া ছাড়াই খুব ধীর করে কার্যকর করা হয়েছিল।


0

আকর্ষণীয় সমস্যা আসলে উভয় ক্ষেত্রে লুপটি অন্তহীন নয়

তবে এগুলির মধ্যে প্রধান পার্থক্য হ'ল এটি কখন শেষ হবে এবং xসর্বাধিক intমান অতিক্রম করতে কত সময় লাগবে যা এর 2,147,483,647পরে এটি ওভারফ্লো অবস্থায় পৌঁছে যাবে এবং লুপটি সমাপ্ত হবে।

এই সমস্যাটি বোঝার সর্বোত্তম উপায় হ'ল একটি সাধারণ উদাহরণ পরীক্ষা করা এবং এর ফলাফলগুলি সংরক্ষণ করা।

উদাহরণ :

for(int i = 10; i > 0; i++) {}
System.out.println("finished!");

আউটপুট:

finished!
BUILD SUCCESSFUL (total time: 0 seconds)

এই অসীম লুপটি পরীক্ষা করার পরে এটি শেষ হতে 1 সেকেন্ডেরও কম সময় লাগবে।

for(int i = 10; i > 0; i++) {
    System.out.println("infinite: " + i);
}
System.out.println("finished!");

আউটপুট:

infinite: 314572809
infinite: 314572810
infinite: 314572811
.
.
.
infinite: 2147483644
infinite: 2147483645
infinite: 2147483646
infinite: 2147483647
finished!
BUILD SUCCESSFUL (total time: 486 minutes 25 seconds)

এই পরীক্ষার ক্ষেত্রে আপনি প্রোগ্রামটি শেষ করে শেষ করতে এবং শেষ করতে শেষ হওয়া সময়ের মধ্যে একটি বিরাট পার্থক্য লক্ষ্য করবেন।

আপনি যদি ধৈর্য না রাখেন তবে আপনি ভাববেন যে এই লুপটি অন্তহীন এবং শেষ হবে না তবে বাস্তবে এটি সমাপ্ত হতে এবং iমূল্য থেকে ওভারফ্লো অবস্থায় পৌঁছাতে কয়েক ঘন্টা সময় লাগবে ।

লুপের জন্য প্রিন্ট স্টেটমেন্টটি ভিতরে রাখার পরে শেষ পর্যন্ত আমরা উপসংহারে পৌঁছেছি যে প্রিন্ট বিবৃতি ছাড়াই প্রথম ক্ষেত্রে লুপের চেয়ে অনেক বেশি সময় লাগবে।

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

আমি এই ক্ষেত্রে এই পরীক্ষা:

লেনোভো 2.7 গিগাহার্টজ ইন্টেল কোর আই 5

ওএস: উইন্ডোজ 8.1 64x

আইডিই: নেটবিয়ানস 8.2

প্রোগ্রামটি শেষ করতে প্রায় 8 ঘন্টা (486 মিনিট) সময় লাগে।

এছাড়াও আপনি খেয়াল করতে পারেন যে লুপের জন্য ধাপে বৃদ্ধিটি সর্বোচ্চ ধাপের মানটিতে i = i + 1পৌঁছানোর জন্য খুব ধীর ফ্যাক্টর।

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

যদি আমরা এটি রাখি i = i * 10এবং পরীক্ষা করি:

for(int i = 10; i > 0; i*=10) {
           System.out.println("infinite: " + i);
}
     System.out.println("finished!");

আউটপুট:

infinite: 100000
infinite: 1000000
infinite: 10000000
infinite: 100000000
infinite: 1000000000
infinite: 1410065408
infinite: 1215752192
finished!
BUILD SUCCESSFUL (total time: 0 seconds)

আপনি দেখতে পাচ্ছেন এটি আগের লুপের সাথে তুলনা করে খুব দ্রুত

প্রোগ্রামটি শেষ করতে এবং শেষ করতে এটি 1 সেকেন্ডেরও কম সময় নেয়।

এই পরীক্ষাটি উদাহরণ আমার মনে হয় এটা সমস্যা নির্মল এবং বৈধতা প্রমাণ করা উচিত পর Zbynek Vyskovsky - kvr000 এর উত্তর , এছাড়াও এটি এই উত্তর হতে হবে প্রশ্ন

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