logicface
@logicface
Начинающий

Не могу сделать аналог вывода простых чисел. В чем проблема?

Я решил научиться в JS и стал проходить уроки по книге Современный учебник JS. Никаких проблем у меня не было и все шло хорошо до тех пор пока я не дошел до урока о выводе простых чисел из 88 страницы Современного учебника. Сам я совершенно не допетрил до того как по простому сделать эту штуку и посмотрел принцип решения. Решил сделать это не на циклах for а на циклах while. Итог: засел я на 4 часа и в конце концов впал в пучину отчаяния.

Однако, как мудрый и терпеливый воин, я не стал сразу забрасывать это дело, но начал по всякому пытаться понять - почему у меня не получается. Я насиловал себя и бедный JS: вставлял alert'ы для проверки переменных в начало и конец внешнего цикла, вставлял и во внутренний цикл вместо конструкций из if и continue. Это я делал для того, чтобы проверить тот факт, что первая переменная (i) всегда опережает внутреннюю (j) после первой итерации, а внутренняя в свою очередь просчитывает все значения от 2 до значения (i) перед тем как передать итерацию внешнему циклу и увеличить (i) на единицу.

Эта битва шла долго, но ничего не работало как надо. В конце концов я решил вынести переменные из примера учебника за циклы и обнаружил что тогда все тоже перестает работать. Я совсем перестал понимать почему так происходит. Я отчаялся... Но друзья, объясните мне пожалуйста почему так происходит и что мне нужно почитать и выучить чтобы хорошенько это понять и осознать. Чтобы я я не тупил, ибо я не хочу оставаться тупым, поверженным долу и втоптанным в землю воином сим элементарным книжным примером.

Прошу вас сенъёры фронт-энда не гнушайтесь быдлокодерских примеров: помогите. Объясните доходчиво как для самых маленьких (разжевать и положить в рот) чем отличается правильная работа скрипта от того, что сделал я (Я не понимаю как себя ведут переменные и почему все встает клином в последнем примере кода). И вообще можно ли мой вариант через while привести к рабочему виду. Примеры кода ниже:

Рабочий пример из учебника:
let n = 10;
nextPrime: for (let i = 2; i <= n; i++) {
for (let j = 2; j < i; j++) {
if (i % j == 0) continue nextPrime;
}
alert(i);
}


Вот что сделал я вначале (переменные ++i и ++j я тоже пытался размещать в разных местах):
let i = 2;
let j = 2;
butthurt: while (i <= 10) {
while (j < i) {
if (i % j == 0) continue butthurt;
++j;
}
alert(i);
++i;
}


Как я изменил пример из учебника, после чего он тоже перестал работать.
let n = 10;
let i = 2;
let j = 2
nextPrime: for (; i <= n; i++) {
for (; j < i; j++) {
if (i % j == 0) continue nextPrime;
}
alert(i);
}


Это последнее что мне удалось из себя выжать спустя несколько часов. Я совсем запутался и уже не могу понять почему так происходит и все стопорится, хотя если убрать строку if (i % j == 0) continue butthurt, циклы считаются нормально.

let i = 2;
let j = 2;
butthurt: while (i <= 10) {
while (j < i) {
alert("Внутренний цикл " + j);
if (i % j == 0) continue butthurt;
++j;
}
alert("Внешний цикл " + i);
j = 2;
++i;
}
  • Вопрос задан
  • 160 просмотров
Решения вопроса 3
Compolomus
@Compolomus
Комполом-быдлокодер
чтоб разобраться как работают вложенные циклы попробуйте напечатать таблицу умножения как на тетрадке сзади, можете даже два варианта где 9 столбиков и где квадратная с цифрами 6376c3a03919f913389813.png
ну а чтоб преобразовать цикл for в цикл while надо просто оставить середину из цикла for (условие выхода) в while, итератор вынести перед циклом (старт), инкримент поместить в тело цикла
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Вы не учли, что оператор continue внутри цикла - это не просто переход, это выполнение очередного шага цикла с изменением счётчика.
let i = 2;
nextPrime:
while (i <= 10) {
  const limit = Math.sqrt(i);
  let j = 2;
  while (j <= limit) {
    if (i % j === 0) {
      j += 1;
      i += 1;
      continue nextPrime;
    }
    j += 1;
  }
  console.log(i);
  i += 1;
}
Ответ написан
sergiks
@sergiks Куратор тега JavaScript
♬♬
Рабочий пример из учебника (с форматированием) хорош предсказуемостью циклов.
Цикл for() сходу устанваливает ограничения и следит за тем, чтобы на каждой итерации все эти i, j увеличивались.

Цикл while() — опасный анархист. Легко впадает в бесконечный цикл, если в каком-то из условий забыть i = i + 1 Что у вас в последней попытке и присутствует:
butthurt: while (i <= 10) {
  while (j < i) {
    alert('Внутренний цикл ' + j);
    if (i % j === 0) continue butthurt;
«Нет выхода», если i % j === 0: никто из них не поменяется и будет крутиться бесконечно.

Как вариант:
const LIMIT = 10;
let i = 2;
while (i <= LIMIT) {
  let j = 2;
  let isPrime = true;
  while (j < i && isPrime) {
    alert(`Внутренний: ${i} / ${j}`);
    if (i % j === 0) isPrime = false; // делится, значит не простое
    j++;
  }
  alert(`Внешний: ${i} - ${isPrime ? 'ПРОСТОЕ' : 'не простое'}`);
  i++;
}
Отказался от меток циклов и от continue – нежелательны именно из-за вносимой путаницы.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы