এই 'জন্য' লুপ থামবে, এবং কেন / কেন নয়? (var i = 0; 1 / i> 0; i ++) এর জন্য {


104

এই forলুপটি কি কখনও থামবে?

for (var i=0; 1/i > 0; i++) {
}

যদি তাই হয়, কখন এবং কেন? আমাকে বলা হয়েছিল যে এটি বন্ধ হয়ে যায়, তবে আমাকে এর কোনও কারণ দেওয়া হয়নি।

Upddate

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


5
এটা থামবে না। কোডের এই পিসটি কার্যকর করার চেষ্টা করুন। (var i = 0; 1 / i> 0; i ++) so কনসোল.লগ (i)
for


3
সংখ্যা।
জিজ্ঞাসা করুন

6
জাভাস্ক্রিপ্ট কি সেই লুপটিকে উপেক্ষা করবে কারণ এর ভিতরে কোনও বিবৃতি নেই? অর্থাত্ এটি অপ্টিমাইজ? আমি জানি কিছু সংকলিত ভাষা রয়েছে যা।
ব্রায়ান জে

3
@ এসকিট, যেমন গননুল এবং অন্যরা নীচের দিকে লক্ষ্য করে, আমরা কখনও বার বার বৃদ্ধি করে অনন্তের কাছে পৌঁছাতে পারি না, তার পরিবর্তে লুপে আটকে যাই Number.MAX_SAFE_INTEGER + 1
এলস্পাইস

উত্তর:


128

(আমি মেটা-সামগ্রীর অনুরাগী নই, তবে: গননুল এবং লে_ম এর উত্তরগুলি সঠিক এবং দরকারী উভয়ই origin সেগুলি মূলত ছিল এবং এই সম্প্রদায় উইকি পোস্ট হওয়ার পরে যে সম্পাদনাগুলি হয়েছিল তা আরও বেশি । এই সিডব্লিউটির আসল প্রেরণা মূলত এই সম্পাদনাগুলির ফলস্বরূপ গেছে, তবে এটি কার্যকর রয়েছে, তাই ... এছাড়াও: এখানে কেবল কয়েকজন লেখক তালিকাভুক্ত থাকলেও, সম্প্রদায়ের আরও অনেক সদস্য মন্তব্যগুলিতে ব্যাপকভাবে সহায়তা করেছেন যা ফোল্ড করা হয়েছে এবং পরিষ্কার করা হয়েছে This নামমাত্র একটি সিডাব্লুও না।)


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

কারণটা এখানে:

  1. প্রাথমিকভাবে, যখন iহয় 0এই শর্তে 1/i > 0সত্য কারণ জাভাস্ক্রিপ্ট মধ্যে হয় 1/0হয় Infinity, এবং Infinity > 0সত্য।

  2. এর পরে, iইনক্রিমেন্ট করা হবে এবং দীর্ঘ সময়ের জন্য ইতিবাচক পূর্ণসংখ্যার মান হিসাবে বাড়তে থাকবে (আরও 9,007,199,254,740,991 পুনরাবৃত্তি)। যাদের ক্ষেত্রে সব মিলিয়ে 1/iথাকবে > 0(যদিও মান 1/iপেতে সত্যিই শেষ দিকে ছোট!) এবং তাই লুপ প্রয়োজন এবং সহ লুপ যেখানে আপ চলতে iমান ছুঁয়েছে Number.MAX_SAFE_INTEGER

  3. জাভাস্ক্রিপ্টের নম্বরগুলি হ'ল আইইই-754 ডাবল-স্পষ্টতা বাইনারি ফ্লোটিং পয়েন্ট, মোটামুটি কমপ্যাক্ট ফর্ম্যাট (b৪ বিট) যা দ্রুত গণনা এবং বিস্তৃত পরিসরের জন্য সরবরাহ করে। এটি একটি চিহ্ন বিট, একটি 11-বিট এক্সপোনেন্ট এবং 52-বিট ইম্প্যান্ট হিসাবে সংখ্যা সংরক্ষণ করে এটি করে (যদিও চতুরতার মাধ্যমে এটি প্রকৃতপক্ষে 53 বিট পায়)। এটি বাইনারি (বেস 2) ভাসমান পয়েন্ট: তাত্পর্যপূর্ণ (আরও কিছু চালাক) আমাদের মান দেয় এবং এক্সপোনেন্টটি আমাদের সংখ্যার বিশালতা দেয়।

    স্বাভাবিকভাবেই, কেবলমাত্র এতগুলি গুরুত্বপূর্ণ বিট সহ, প্রতিটি সংখ্যা সংরক্ষণ করা যায় না। এখানে নম্বর 1 এবং পরের সর্বোচ্চ সংখ্যাটি 1 যে 2 + 5-2 1.00000000000000022, 1 + 2 -52 ≈ 1.00000000000000022 সংরক্ষণ করতে পারে তার পরের সর্বোচ্চ নম্বরটি: 1 + 2 × 2 -52 ≈ 1.00000000000000044

       + + ------------------------------------------------- -------------- সাইন বিট
      / + ------- + ---------------------------------------- -------------- প্রকাশক
     / / | + + ------------------------------------------------- + - গুরত্বপূর্ণ
    / / | / |
    0 01111111111 0000000000000000000000000000000000000000000000
                    = 1
    0 01111111111 0000000000000000000000000000000000000000000001
                    ≈ 1.0000000000000002222
    0 01111111111 0000000000000000000000000000000000000000001010
                    ≈ 1.0000000000000000044
    

    1.00000000000000000022 থেকে 1.00000000000000044 এ লাফটি নোট করুন; 1.00000000000000033 সঞ্চয় করার কোনও উপায় নেই। এটি পূর্ণসংখ্যার সাথেও ঘটতে পারে: Number.MAX_SAFE_INTEGER(9,007,199,254,740,991) সর্বাধিক ধনাত্মক পূর্ণসংখ্যার মান যা ফর্ম্যাটটি ধরে রাখতে পারে iএবং i + 1উভয়ই হুবহু উপস্থাপনযোগ্য ( স্পেস )। 9,007,199,254,740,991 এবং 9,007,199,254,740,992 উভয়ই উপস্থাপন করা যেতে পারে তবে পরবর্তী পূর্ণসংখ্যা 9,007,199,254,740,993, পারবেন না; পরবর্তী পূর্ণসংখ্যা 9,007,199,254,740,992 এর পরে আমরা 9,007,199,254,740,994 এর প্রতিনিধিত্ব করতে পারি। এখানে বিট নিদর্শনগুলি রয়েছে, ডানদিকে (কমপক্ষে গুরুত্বপূর্ণ) বিটটি নোট করুন:

       + + ------------------------------------------------- -------------- সাইন বিট
      / + ------- + ---------------------------------------- -------------- প্রকাশক
     / / | + + ------------------------------------------------- + - গুরত্বপূর্ণ
    / / | / |
    0 10000110011 1111111111111111111111111111111111111111111111111111111111
                    = 9007199254740991 (সংখ্যা।
    0 10000110100 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
                    = 9007199254740992 (সংখ্যা।
    x এক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্স
                      9007199254740993 (সংখ্যা। MAXائشE_INTEGER + 2) সংরক্ষণ করা যায় না
    0 10000110100 00000000000000000000000000000000000000000010001
                    = 9007199254740994 (সংখ্যা।
    

    মনে রাখবেন, ফর্ম্যাটটি বেস 2, এবং সেই ঘনিষ্ঠর সাথে কমপক্ষে উল্লেখযোগ্য বিট আর ভগ্নাংশ নয়; এটির মান 2 রয়েছে এটি বন্ধ (9,007,199,254,740,992) বা (9,007,199,254,740,994) এ বন্ধ হতে পারে; সুতরাং এই মুহুর্তে, আমরা পুরো সংখ্যা (পূর্ণসংখ্যার) স্কেল পর্যন্ত নির্ভুলতা হারাতে শুরু করেছি। যা আমাদের লুপের জন্য নিহিত রয়েছে!

  4. i = 9,007,199,254,740,992লুপ শেষ করার পরে i++, আমাদের i = 9,007,199,254,740,992আবার ... দেয় ; এর কোনও পরিবর্তন নেই i, কারণ পরবর্তী পূর্ণসংখ্যা সংরক্ষণ করা যায় না এবং গণনাটি শেষ হয়ে যায়। iআমরা যদি পরিবর্তন করি i += 2তবে i++এটি পরিবর্তন করতে পারে না। সুতরাং আমরা স্থিতিশীল অবস্থায় পৌঁছেছি: iকখনই পরিবর্তন হয় না এবং লুপ কখনও শেষ হয় না।

এখানে বিভিন্ন প্রাসঙ্গিক গণনা রয়েছে:

if (!Number.MAX_SAFE_INTEGER) {
  // Browser doesn't have the Number.MAX_SAFE_INTEGER
  // property; shim it. Should use Object.defineProperty
  // but hey, maybe it's so old it doesn't have that either
  Number.MAX_SAFE_INTEGER = 9007199254740991;
}
var i = 0;
console.log(i, 1/i, 1/i > 0); // 0, Infinity, true
i++;
console.log(i, 1/i, 1/i > 0); // 1, 1, true
// ...eventually i is incremented all the way to Number.MAX_SAFE_INTEGER
i = Number.MAX_SAFE_INTEGER;
console.log(i, 1/i, 1/i > 0); // 9007199254740991 1.1102230246251568e-16, true
i++;
console.log(i, 1/i, 1/i > 0); // 9007199254740992 1.1102230246251565e-16, true
i++;
console.log(i, 1/i, 1/i > 0); // 9007199254740992 1.1102230246251565e-16, true (no change)
console.log(i == i + 1);      // true


79

উত্তর:

শর্তটি 1/i > 0সর্বদা সত্যকে মূল্যায়ন করবে:

  • প্রাথমিকভাবে এটি সত্য কারণ 1/0মূল্যায়ন করে Infinityএবং Infinity > 0সত্য

  • এটি সত্য থেকে যেহেতু সবার 1/i > 0জন্য সত্য i < Infinityএবং i++কখনও পৌঁছায় না Infinity

কেন i++কখনও পৌঁছায় না Infinity? Numberডেটাটাইপের সীমিত নির্ভুলতার কারণে এখানে একটি মান রয়েছে i + 1 == i:

9007199254740992 + 1 == 9007199254740992 // true

একবারে এই iমানটিতে পৌঁছায় (যা এর সাথে সঙ্গতিপূর্ণ ), এটি পরেও একই থাকবে ।Number.MAX_SAFE_INTEGER + 1i++

আমাদের অতএব অসীম লুপ রয়েছে।


পরিশিষ্ট:

কেন 9007199254740992 + 1 == 9007199254740992?

জাভাস্ক্রিপ্টের Numberডেটাটাইপ আসলে একটি 64-বিট আইইইই 754 ডাবল নির্ভুলতা ভাসা । প্রত্যেকটি পৃথক Numberকরা এবং তিনটি অংশ হিসাবে সংরক্ষণ করা হয়: 1-বিট চিহ্ন, 11-বিট এক্সপোনেন্ট এবং 52-বিট ম্যান্টিসা। এর মান হ'ল -1 চিহ্ন × ম্যান্টিসা × 2 এক্সপোনেন্ট

9007199254740992 কীভাবে উপস্থাপিত হয়? 1.0 × 2 53 হিসাবে , বা বাইনারি:

এখানে চিত্র বর্ণনা লিখুন

ম্যান্টিসার সর্বনিম্ন উল্লেখযোগ্য বিট বৃদ্ধি করা, আমরা পরবর্তী উচ্চতর সংখ্যাটি পাই:

এখানে চিত্র বর্ণনা লিখুন

এই সংখ্যাটির মান 1.0000000000000000022… × 2 53 = 9007199254740994

ওটার মানে কি? Numberহয় 900719925474099 2 বা 900719925474099 4 হতে পারে তবে এর মধ্যে কিছুই নয়।

এখন, আমরা কোনটি 900719925474099 2 + 1 উপস্থাপন করতে বেছে নেব ? আইইইই 754 rounding নিয়ম 900719925474099: উত্তর দিতে 2


9
সংক্ষিপ্ত এবং সঠিক, বর্তমান গৃহীত উত্তরের চেয়ে ভাল
অ্যালেক্সওয়েন

@ অ্যালেক্সউইন গৃহীত উত্তর হ'ল একটি সম্প্রদায়ের উইকি গৃহীত উত্তর।
ফুলভিও

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

"আমি ++ কখনই অনন্তে পৌঁছায় না? সংখ্যার ডাটাটাইপের সীমিত নির্ভুলতার কারণে ..." <- নিশ্চয় এটি কখনও অসীম পৌঁছাবে না এমনকি এমনকি অসীম-নির্ভুলতার সংখ্যার প্রকারের সাথেও .. আপনি জানেন যে আপনি গণনা করতে পারবেন না অনন্ত: পি
ব্লারগবার্ড

1
@ ব্লগারবার্ড আপনি সীমিত নির্ভুলতা দ্বিগুণের সাথে অনন্তকে গণনা করতে পারেন , আপনাকে কেবল 1 এর চেয়ে অনেক বড় সংখ্যার দ্বারা বৃদ্ধি করতে হবে, যেমন for (var i = 0; i < Infinity; i += 1E306);। তবে আপনি যেখান থেকে আসছেন তা আমি পেয়েছি;)
লে_ম

27

Number.MAX_SAFE_INTEGERধ্রুব জাভাস্ক্রিপ্ট সর্বোচ্চ নিরাপদ পূর্ণসংখ্যা প্রতিনিধিত্ব করে। MAX_SAFE_INTEGERধ্রুব একটি মান আছে 9007199254740991। এই সংখ্যার পিছনে যুক্তি হ'ল জাভাস্ক্রিপ্ট আইইইই 754 তে উল্লিখিত হিসাবে ডাবল-স্পষ্টতা ফ্লোটিং-পয়েন্ট ফর্ম্যাট নম্বরগুলি ব্যবহার করে এবং কেবল নিরাপদে - (2 53 - 1) এবং 2 53 - 1 এর মধ্যে সংখ্যা উপস্থাপন করতে পারে ।

এই প্রসঙ্গে নিরাপদ পূর্ণসংখ্যার প্রতিনিধিত্ব করার ক্ষমতা এবং সঠিকভাবে তাদের তুলনা করার জন্য বোঝায়। উদাহরণস্বরূপ, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2এটি মূল্যায়ন করবে true, যা গাণিতিকভাবে ভুল। দেখুন Number.isSafeInteger()আরও তথ্যের জন্য।

কারণ MAX_SAFE_INTEGERএটি একটি স্থিতিশীল সম্পত্তি Number, আপনি সর্বদা এটি তৈরি করেছেন Number.MAX_SAFE_INTEGERএমন কোনও Numberবস্তুর সম্পত্তি হিসাবে না বরং ব্যবহার করুন ।

হালনাগাদ:

মুছে ফেলা একটি উত্তরে এমন কেউ উল্লেখ করেছেন: iকখনই অনন্ততায় পৌঁছায় না। একবার এটি ছুঁয়েছে Number.MAX_SAFE_INTEGER, i++পরিবর্তনশীল আর বাড়ায় না। এটি আসলে সঠিক নয়

@TJ Crowder মন্তব্য যে i = Number.MAX_SAFE_INTEGER; i++; i == Number.MAX_SAFE_INTEGER;হয় false। কিন্তু পরবর্তী পুনরাবৃত্তি একটি অপরিবর্তনীয় অবস্থায় পৌঁছেছে, সুতরাং মূল উত্তরটি সঠিক।

iউদাহরণে কখনও পৌঁছায় না Infinity


2
বিশেষত, 9007199254740992 + 1হয় 9007199254740992
কোবি

1
@ গেরার্ডোফুর্তাদো আমি এটি কল্পনা করেছিলাম।
ফুলভিও

1
@GerardoFurtado for (var i=0; NaN > 0; i++) { console.log(i); }কিছু উত্পাদন করা হবে না।
ফুলভিও

2
@ জেরার্ডোফুর্তাদো: সেক্ষেত্রে লুপটি থামবে। লুপ শরীর আদৌ কখনো প্রবেশ করানো হবে, প্রথম পরীক্ষা (যেহেতু 1/i > 0), মিথ্যা হবে যেহেতু যদি iহয় 0, 1/iহয় NaN, এবং NaN > 0মিথ্যা।
টিজে ক্রোডার

1
@ টিজে ক্রাউডার আমি আমার উত্তর আপডেট করেছি। যে ইশারা জন্য ধন্যবাদ!
ফুলভিও
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.