Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Рекурсия - JavaScrit (https://javascript.ru/forum/misc/67330-rekursiya-javascrit.html)

AndriyNNNNN 11.02.2017 00:51

Рекурсия - JavaScrit
 
Помогите пожалуйста!
Выполнение задания обязательно должно включать использование рекурсивной функции:
Проверить, введенное ли число есть простым?

Paguo-86PK 11.02.2017 12:32

Тaк торопиться надо, что даже буквы глотаются - Рекурсия - JavaScript?:blink:

P.S.: В гугле море ссылок на готовые алгоритмы…

DivMan 13.02.2017 21:39

function foo(chislo){
	while(true){
  	if(chislo % 2 != 0){
  		return chislo + ' Простое число';
  	}
    else{
    	return foo(chislo + 1);
    }
  }
}

alert(foo(2));

рони 13.02.2017 21:42

DivMan,
:blink:

DivMan 13.02.2017 22:12

Цитата:

Сообщение от рони (Сообщение 444211)
DivMan,
:blink:

Что?

рони 13.02.2017 22:17

Цитата:

Сообщение от DivMan
Что?

Цитата:

Сообщение от AndriyNNNNN
Проверить, введенное ли число есть простым?

ввели 2 выдало 3 - не осилил

DivMan 13.02.2017 22:19

Если введённое число, не простое, то его пропустить и проверить следующее число, если оно простое вывести его и так далее.

Что тут неправильного?

рони 13.02.2017 22:21

DivMan,
ввели 2 выдало false, ввели 3 выдало true

DivMan 13.02.2017 22:22

так и должно быть, по моей задумке. Тогда какой смысл проверять рекурсией, только введённое значение?

рони 13.02.2017 22:27

Цитата:

Сообщение от DivMan
Тогда какой смысл проверять рекурсией, только введённое значение?

что бы узнать какое число ввели простое или нет

рони 13.02.2017 22:30

DivMan,
function foo(chislo){
  while(true){
  	if(chislo % 2 != 0){
  		return chislo + ' Простое число';
  	}
    else{
    	return foo(chislo + 1);
    }
  }
}

alert(foo(25));

5 * 5 = 25!!!
Цитата:

Просто́е число́ — натуральное (целое положительное) число, имеющее ровно два различных натуральных делителя — единицу и самого себя

DivMan 13.02.2017 22:54

Я не знаю, как сделать условие

рони 13.02.2017 23:36

DivMan,
вариант без рекурсии, проверка числа на все возможные делители
function testPrime(number) {
    var isPrime = number == 2|| number == 3;
    var checkNumber = Math.sqrt(number);
        for (i = 2; i <= checkNumber; i++) {
        if (number % i == 0 && number != i) {
                isPrime = false;
                break
            } else isPrime = true;
        }

    return isPrime
}

alert(testPrime(23));

Diphenyl Oxalate 14.02.2017 11:11

function IsPrime( N, M ) {
	M = M || Math.floor( N / 2 );
	return N % M == 0 ? false : M == 2 ? true : IsPrime( N, M - 1 );
}

alert( [IsPrime(22), IsPrime(23)] );

рони 14.02.2017 12:11

Diphenyl Oxalate,
отимальнее считать не c N / 2 а с квадратного корня числа.
function IsPrime( N, M ) {
  M = M || Math.sqrt(N)|0;
  return N % M == 0 ? false : M == 2 ? true : IsPrime( N, M - 1 );
}

alert( [IsPrime(22), IsPrime(23)] );

Malleys 16.02.2017 15:38

рони,
ваш алгоритм считает 2 и 3 за составные числа.

Оптимальнее проверять не все делители подряд от 2 до sqrt(N), а только простые делители. Например, если мы проверили делимость на 2, то нет необходимости проверять остальные числа кратные 2. (Т. е. нужно тогда проверить только 2, 3, 5, 7, 9, ..., sqrt(N) )

Можно уменьшить количество делителей предприняв тот же шаг для следующего простого числа -- 3. Тогда у нас останутся числа не кратные 2 и 3. (Теперь нужно проверить только 2, 3, 5, 7, 11, 13, 17, 19, ..., sqrt(N)) Легко заметить, что после 2 и 3 идут числа вида 6n ± 1

Т. е. после того как нашли наибольший делитель sqrt(N), необходимо его привести к виду 6n ± 1. Полученный делитель должен быть меньше либо равен sqrt(N).

function isPrime(number) {
  // простые числа 2 и 3
  if(number == 2 || number == 3)
	  return true;

  // определяем составные числа:
  // кратные 2 и 3 больше 1, остаются числа вида 6n ± 1, где n > 0, n ∈ Z
  if(number < 2 || number % 2 == 0 || number % 3 == 0)
	  return false;

  // steps[остаток от деления делителя на 6] == число, на которое увеличить делитель, чтобы получилось число вида 6n ± 1
  var steps = [-1, -2, -1, -2, -3, -4];

  // делитель приводим к виду 6n ± 1
  var i = Math.sqrt(number) | 0;
  var divider = (i - (i - 5) % 2 - 2 * (1 - Math.ceil(((1 + ((i - 5) / 2) | 0) % 3) / 2)));
  return isPrime(number, divider);

  function isPrime(number, divider) {
	  divider = divider;

	  // проверили все делители и пришли сюда?
	  // значит число простое
	  if(divider == 1) return true;

	  // после того как проверили делимость на 5,
	  // делаем вывод (на 2 и 3 нет смысла проверять,
	  // т. к. здесь могут быть только не кратные 2 и 3)
	  return number % divider == 0 ? false : divider == 5 ? true : isPrime(number, divider + steps[divider % 6]);
  }
}

alert([22, 23].map(function(v) {
	return v + " " + isPrime(v)
}).join("\n"));


Поскольку от 6n до 6(n + 1) только два числа не кратных 2 и 3, то на каждые 6 чисел из ряда 2, ..., sqrt(N) алгоритм выбирает 2 числа.
Это означает, что для проверки числа по этому алгоритму необходимо в 3 раза меньше делителей, чем в ряду 2, ..., sqrt(N)

Diphenyl Oxalate 16.02.2017 16:04

Malleys,
Ваш код работает медленнее.
10к итераций за 50мс против 35мс у скрипта выше

рони 16.02.2017 16:10

Malleys,
ок

рони 16.02.2017 16:24

Цитата:

Сообщение от Malleys
ваш алгоритм считает 2 и 3 за составные числа.

исправил
var isPrime = number == 1|| number == 3;
на 2
пост №13
если вы про код в №15 - то там да надо дополнить алгоритм

Malleys 22.01.2019 22:02

Цитата:

Сообщение от Diphenyl Oxalate
Ваш код работает медленнее.

Да, там достаточно ресурсо-затратное вычисление следующего кандидата на простое число. Особенно потому, что я пытался вычислять простые числа через рекурсию. Простые числа могут принадлежать множеству { 2, 3, 6n ± 1 }, где n > 0, n ∈ Z, и через цикл с шагом 6(а не с шагом 1, как в посте №13) оно же в 3 раза меньше чисел будет проверять, не так ли?

function isPrime(number) {
	if(number === 2 || number === 3)
		return true;

	var limit = 1 + Math.sqrt(number);

	if(number < 2 || number % 2 == 0 || number % 3 == 0)
		return false;

	for(var index = 6; index <= limit; index += 6) {
		if(number % (index - 1) === 0) return false;
		if(number % (index + 1) === 0) return false;
	}

	return true;
}

alert([22, 23].map(function(v) {
    return v + " " + isPrime(v)
}).join("\n"));

рони 22.01.2019 22:51

Malleys,
:) :thanks:


Часовой пояс GMT +3, время: 10:58.