Как определить простое число в 1с

Обновлено: 07.07.2024

Здравствуйте! Задание: Найти количество все простых чисел в диапазоне от 0 до 1000. Помогите доработать код. Не понимаю чего не хватает.

Та же проблема: не понимаю что вам в нем не нравится. так у вас в итоге выводится только количество чисел, а вы вроде как хотите получить сами числа.. да и само условие странное Извиняюсь, неправильно описал задание. Мне нужно количество. В результате выводит 0.

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

Чтобы программно проверить простое число или нет достаточно проверить не делится ли это число на числа до квадратного корня из этого числа. Если делится - число не простое, в противном случае - простое.

Для определения, является ли число простым напишем метод, который определяет простое число или нет:

Теперь собственно говоря сам код, в котором будем вызывать метод:

В Вашем случае условие не правильное. Вот познавательная страница: Как проверить, является ли число простым


13.8k 12 12 золотых знаков 36 36 серебряных знаков 60 60 бронзовых знаков Ой, подскажите как вызывать прогу в консоли вне Эклипса. Думаю, что Вам достаточно запустить исполняемый файл .exe , который получился в результате. вроде не до половины, а до квадратного корня из числа

Решение уже написали, тем не менее считаю что в данном случае имеет смысл подробно разобрать ошибку автора.

Итак, исходное условие предложенное автором выглядит так

Разберем его на части:

i % i == 0 Это условие всегда истинно, т.к. остаток от деления любого числа на это же число всегда равен 0.

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

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

Надо понимать, проверку что число делится без остатка на себя и 1 пройдет абсолютно любое число, даже не целое. А из определения следует, что нет других чисел на которые можно разделить число без остатка и именно это нужно проверять.

PS: Жаль что приходится объяснять этот довольно простой по сути факт вместо вашего преподавателя математики, и далеко не факт что в этом виноват преподаватель. И учтите. что без хорошего знания математики в программировании делать то в общем нечего, так что восстанавливайте пробелы в математике пока не поздно.

Что может быть проще простых чисел ? По определению, целое число называется простым, если оно не может быть представлено, как произведение двух меньших чисел. Единственное четное простое число - 2. Все остальные простые числа нечетные. Самый древний алгоритм поиска простых чисел получил название "решето Эратосфена". Это известная история и останавливаться на ней не будем. Сразу перейдем к заявленной теме, а именно, поиску простых чисел с помощью запроса на встроенном языке платформы 1С:Предприятие. Исходным объектом для поиска будет таблица натуральных чисел в диапазоне от 1 до заданного верхнего предела. Подобную таблицу, можно формировать в запросе , но мы упростим себе жизнь и заполним её с помощью операторов встроенного языка.

Рассмотрим первый алгоритм. Построим соединение двух одинаковых таблиц, сформированных на первом этапе. В характеристиках связи зададим условие, что левый множитель меньше или равен правому, плюс потребуем,чтобы произведение этих чисел было меньше максимального числа в исходной таблице. Для каждой образованной пары чисел вычислим произведение.Ниже приведен пример для набора чисел меньше 9. Исходная таблица

НатуральноеЧисло
1
2
3
4
5
6
7
8
9

Пары чисел, образованные при внутреннем соединении таблицы со своей копией при заданных ограничениях.

Левое Правое Произведение
1 1 1
1 2 2
2 2 4
1 3 3
2 3 6
3 3 9
1 4 4
2 4 8
1 5 5
1 6 6
1 7 7
1 8 8
1 9 9

Исходная таблица содержала 9 строк, итоговая 13. Среди чисел в колонке Произведение есть повторяющиеся. Это числа 4,6 и 9. Числа 1,2,3,5,7 встречаются только один раз. Единицу из этого ряда надо исключить. Оставшиеся четыре числа будут первыми в ряду простых чисел. Приведем текст запроса:

Запрос возвращает количество простых чисел в первоначальном диапазоне.Приведенный алгоритм отличается простотой, но увы, слишком медленный. Постараемся придумать, что-то быстрее.

Как проверить, что число А делится без остатка на число Б. Во встроенном языке есть оператор %, который возвращает остаток от деления. В языке запросов такая опция отсутствует. Поэтому воспользуемся следующим приемом :

Если это выражение истинно, то Б является делителем числа А. Идея запроса следующая. Организуем внутреннее соединение исходной таблицы со своей копией, где в качестве условия выступает представленная выше проверка на делимость. Понятно, что число Б должно быть меньше числа А. Более того, число Б должно быть меньше корня квадратного из А. Квадратный корень в запросе мы вычислить не можем, но мы можем найти целое приближение к квадратному корню.

Сформируем таблицу с квадратами наших исходных чисел.Теперь соединим данную таблицу с исходной. Полученную набор сгруппируем по исходным числам, а для квадратов применим функцию МИНИМУМ(). Текст запроса приведен ниже:

Во временной таблице мКорни в колонке Н содержится число из исходного набора, а в колонке Корень, минимальное число,квадрат которого больше или равен Н. А теперь соберем все вместе:

Любопытно проверить, как различаются скорость выполнения первого и второго запроса (время в миллисекундах):

Верхняя граница 1000 2000 3000 4000 5000
Вариант 1 492 795 1229 2314 3061
Вариант 2 651 954 1644 2955 4364

Видим, что первый вариант запроса отрабатывает быстрее. Для второго можно "проредить" исходные данные, а именно убрать все четные числа кроме двойки (это уже элемент алгоритма "решето Эратосфена").

Очевидно, что после такой операции скорость должна увеличиться, что и показывают замеры (время в миллисекундах):

Верхняя граница 1000 2000 3000 4000 5000
Вариант 1 492 795 1229 2314 3061
Вариант 2 (ускоренный) 268 842 1163 1373 1587

Посмотрев решения от Сергея (ildarovich) , решил добавить экзотику в виде решета Аткина. Максимальное значение верхней границы в приведенном примере - 100 000. Параметры запроса - Граница и КореньИзГраницы. Все простые числа <= 100 000 программа находит за 3 сек. Результат хуже чем у Сергея (ildarovich), но тоже неплохой.

Нам осталось сказать, где это можно использовать. Разумеется, ни в одной типовой конфигурации такие задачи не встречаются. Но подобный вопрос может встретиться на собеседовании при приеме на работу. Теперь вы знаете, как на него ответить.

Сколько же всего сложного и таинственного нас окружает.

Черные дыры и сновидения. Темная материя и подсознание. Корпускулярно-волновой дуализм и 1С.

И ведь думаешь, что знаешь эту "1Ску" как свои пять пальцев, но стоит случайно копнуть глубже. И очередная багофича. Да ешё и какая!

В этой статье рассмотрим секретный оператор ?

О нём мало кто знает, хоть он и существует как минимум с версии 8.0.


В последнее время я публикую на своём телеграм-канале разные хитрые задачки с подвохом для программистов 1С. Какие-то беру "по памяти", а какие-то "рождаю" в результате экспериментов. Об этом скоро выйдет отдельная статья. И вот в очередном тесте адекватности платформы случайно натыкаюсь на такую конструкцию:

Синтаксис-проверка прошла успешно. Никаких ошибок не высветилось. И, казалось бы, ошибка тогда должна произойти в момент выполнения.


Код успешно выполнился. Удивительно, но сработало! И тут меня понесло.


Как оказалось, знак ? ведёт себя крайне странно. Давайте посмотрим ещё раз прошлый пример.

Мы создаём новую переменную и назначаем ей значение - ?. И в переменной находится Неопределенно. И, казалось бы, это и есть ответ на вопрос. Знак ? означает Неопределено.

Но что же тогда это:


В данном коде сначала идёт объявление переменной "А". И в А установлено числовое значение "1". А далее идёт наше сравнение с ?. Если бы под знаком вопроса скрывалось Неопределено, то мы бы не попали внутрь условия. А по скрину видно, что попали.


Очень странная ошибка. "Переменная не определена (Сообщить)". Ну допустим. Добавим тогда такую переменную:

Данный код компилируется без ошибок. И при выполнении в 1С сообщает "ТЕСТ". То есть значение переменной Сообщить

Выходит, что символ ? указывает на предыдущее слово в коде. В данном случае, перед ? было слово Сообщить. И поэтому 1С изначально поругалась, что такая переменная не определена. А когда мы добавили переменную Сообщить, то всё стало на свои места.

То есть наш код для 1С выглядит так:

А теперь вернемся к нашим предыдущим примерам и разберём что и как сработало.

В данном коде предыдущее слово перед ? - Если. Но оно является ключевым для 1С. Как "Цикл", "Процедура" и так далее. Поэтому, его оператор ? не учитывает и берет в качестве источника значения переменную А.

Скорректируем же этот код так, как его видит 1С:

Теперь всё логично. А = А и поэтому условие выполняется.

А что с нашим самым первым примером?

На самом деле всё так же. Просто заменяем знак вопроса на предыдущее слово.

Да, такой код тоже странный, но в рамках 1С всё логично. Сначала объявляется переменная и в ней Неопределено. А затем происходит присвоение переменной значения из её самой. То есть опять же Неопределено. Можете проверить такой код - это хоть и выглядит странно, но работает. А почитать чуть подробнее можно в статье на ИТС: МояПеременная = 0; МояПеременная = ? + 1; //1 МояПеременная = ? + 1; //2 МояПеременная = ? * 5; //10 МояПеременная = ? / 2; //5 МояПеременная = ? - 6; //-1

А самое интересное, что такая возможность существовала как минимум ещё с версии 8.0 . Специально скачал старую платформу и проверил.

На самом деле такой код можно ещё упросить:

Но такой вариант становится менее надежным. Ведь всё работает до тех пор, пока перед ? находится МояПеременная. Если же вставить после этого какое-то другое "слово", то всё порушится.

Но вот ещё пример:

Мы же помним, что знак ? берет предыдущее слово. Так вот в нашей строке кода это слово "А". Именно так - без "Структура".

Поэтому 1С в таком коде вместо знака вопроса вставит "А"

Но зато появляется новая возможность применения:

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

А вот ещё пример. Можно передать в какой-то метод или конструктор одно значение несколько раз:

Передавать знак ? можно даже в условный тернарный оператор. Например, этот код приводит отрицательные числа к 0:

А этот приводит отрицательные числа к положительным:

Подобным образом можно присваивать дефолтные значения необязательным параметрам:

Главное помнить, что знак ? берет именно предыдущее слово, поэтому вот так работать НЕ будет:

1С поругается, что Переменная не определена (Структура). Ведь перед последним знаком ? слово Структура

Но что если использовать символ ? в параметрах?

Сделаем процедуру с параметром ? :

Такую процедуру действительно возможно создать. И можно вызывать. Причем 1С понимает, что параметр обязательный и его необходимо передать.

Но мы можем сделать его необязательным:

И параметр не обязан быть единственным. Можно делать разными способами:

А можно использовать Знач

Но вот незадача, ? в параметре метода не использует предыдущее слово (как во всех других случаях). Как обратиться к этому параметру - неизвестно.

В стеке вызовов он отображается:


А попробуем добавить второй параметр ?

1С ругается так:

Формальный параметр с указанным именем уже определен (?)

Опираясь на текст ошибки, мы можем предположить, что 1С объявляет параметр с именем "?"

И когда мы пытаемся добавить ещё один такой параметр, то платформа ругается.

Как обратиться к параметру с именем "?" - неизвестно. Методы Вычислить() и Выполнить() не помогли.

Но, возможно, это всё те вопросы, которые нам ещё предстоит разгадать. Секреты и загадки этой таинственной платформы под кодовым названием 1С.


Понравилась статья?

Поставьте лайк плюс. Пишите свои идеи и комментарии по теме. Статья будет дополняться.

Дано: много строк (>10000), длина каждой < 40 символов, могут содержать любые алфавитно-цифровые символы, точки и запятые.
Задача: нужно максимально быстро определить, является ли эта строка числом. При этом строка, являющаяся числом, может содержать нули в старших разрядах и нули на хвосте дробной части. Разделителем разрядов может быть как точка, так и запятая. Знака изначально в строке быть не может, поэтому на + и - пофиг.
Например числа:
0100,99900
100
100.99
Не числа:
100.0,12
Asd100xЩ
100.0Ю
Предложите быстрый алгоритм, плз?

умножить на любое число, например 1. если ругнётся - не число.
Попытка, Исключение

(1) Не. Стр*1 - Операция умножения не определена для строковых величин, 1*Стр - умножит всегда, преобразовав по правилам Число()

Если б не нули в начале и конце, прокатило бы:
.
с предварительной заменой запятой на точку. А с нулями - хз.
Очень не хочется посимвольно разбирать строку, ибо много их.

(6) п. 1 - я сходу вижу только посимвольным разбором. Чего как-раз и не хочется. Как быстро нули посчитать?
(7) Игра ума. Лучше алгоритм предложи. Быстрый.
(8) Потому что Число("123") - это число. А число не равно строке. Засунь в конфигуратор - увидишь.

(10) Это написано в (3). Для строки "0100" условие не выполняется. Я ж говорю - проблема в нулях.

(12)не взлетит
(11) без посимвольного не обойтись, на этапе отсечения нулей - перебор будет короче всего

(12) Повезло тебе, что не на китайском пишешь. У них там, грят, около 5000 основных иероглифов. У какая длинная строка с Найти() была бы ;)

если (3) катит с предварительной заменой точек и запятых.
то замени в исходной строке Стр все "0" на любую другую цифирь

(0) а в принципе, как такая задача родилась?
Тест что ли какой-то?

(18) скорее всего автор хочет привести все Наименования какого-то Справочника к числовому виду

(19)Скорее, коды. Когда нарушают уникальность, потом начинают вводить всякую чепуху.

(20) м.б. автор хочет производить какие-то матоперации с наименованиями.
м.б. это лотерейные билеты или номера скидочных карточек покупателя.
(21) коды я отмёл сразу - (22) прав. самое бОлшее я видел 15 знаков кода.

(22) хотя да.
(23) жизни вы не видели, я видела 100:) Они туда закодировали производителя, иерархию и пр.

(24) Боже!
а зачем же так код мучать? реквизит в Справочник нельзя добавить?

(23) На мой взгляд, для решения этой задачи, надо знать полностью условие, потому как от условий возможна разная реализация, сама по себе задача решаема в лоб без всяких проблем, если она единовременная, то можно плюнуть на быстродействие. Допустим, если автор действительно хочет "перекодировать" справочник, то нужен дополнительный алгоритм, потому как при использовании одного алгоритма преобразования строки состоящей из одних цифр или из цифр и каких-то символов в число, может "задвоится" число, т.е. при одинаковом преобразовании строки цифр и строки символов имеем вероятность получить на выходе одно и то же число.

(28) логично. об уникальности я не подумал.
0099.9, 099.9, 99.990 дадут одно число 99.9

Если нужно просто "достать число" - то есть очень простой способ извлечения числа из строки, без перебора.

ре.test(вСтрока)
В точности не уверен, можно потестировать если надо.

(42) Я понял, что нужно еще определить само значение если строка является числом.

(45) :-)
0 будет только если проверяемое выражение начинается не с цифры. А все первые цифры буду превращаться в число, остальное отбрасываться.

(53) Ограничение знаков после запятой. Для 1С это не число

В терминах поставленной задачи эта строка - число, со значением в 1С, равным нулю.

"1.00000000000000000001" - числом.
Потому как все попытки сравнивать строки до и после преобразования функцией "Число", натыкаются на ограниченность разрядов.

(57) можно и не определяться, по такому принципоу пойти
Число("1"+".000000000000000000001"+"1")*10000000000000000000000

(58) не фигня, так многое можно определить и не только строка или число

(59)
Число("1"+"9876543210"+"1")*1000000000000000000000000000000000000000 =
198765432101000000000000000000000000000000000000000

(58)(59) а это - Число("1толиДатолиНет"+".000000000000000000001"+"1")*10000000000000000000000 число ?

(61) Не, ну понятно. Я сказал что принцып такой. Позицию разделителя дробной найти.

(53) Как я понял, 1С не видит больше 20 знаков после точки.
Тогда можно извернуться так.
Часть вторая.усовершенствованная :-):
--------------------

Ну, ладно, это я уже стебаюсь.
Имхо можно эти способы объединить или выбрать более удобный для (0).

КодСимв(<?>)
Синтаксис:
КодСимв(<Символ>)
Назначение:
Возвращает код первого символа, содержащегося в строке.
Параметры:
<Символ> - строковое выражение.

(67)
То и вернет, что строка является числом, и его значение.
Фишка в том, что число в 1С ограниченно 69 разрядами (чего хватает для этой задачи), но при преобразовании его в строку обрезает до 23 знаков после запятой.

(66)
Неправильно отработает, если будет две точки, и они попадут в разные части.
Либо в середине строки будут пробелы, которые попадут в первую часть в конец, во вторую часть в начало.

(71) Легко решается несколькими строками в начале процедуры Сформировать
:-)

не всеже объясните тупым и алкоголикам чем шаблон плох ? медленно ?

(75) Только еще одно уловие поставить надо, если нет дробной части. Просто хотелось не перебором.
(74) Ну чего ты этими шаблонами добьешься? Попробуй че нить подсунуть. К примеру 00А00.5115.1

(76) Не надо доп. условий, там в комментарии пояснено, почему не надо. И перебора там нет - СтрЗаменить-то без перебора работает.
(78) Спортивно средствами встроенного языка.

такое чувство, что из предложенных вриантов не все тестировали (больше писали на угад) + кто скажет что быстрее ? :)
П.С. сам пока думаю. :)

Мда. Не ожидал я такого спортивного интереса, когда тему поднимал :)
Сразу повторю свой ответ на вопрос "а на хрена?" - это действительно игра ума :) Была реальная, но разовая задача, сделал ее "в лоб" перебором, потом стало интересно, а как быстрее, поставил граничные условия, запостил сюда, пошел домой спать :)
Самый быстрый вариант, как ни странно, оказался самым первым, у 2Green. Но он не работает с числами >20 знаков. Результат меня сильно удивил, потому как я думал о первом варианте Рэйва.
Замер производительности показал:
(В тиках - 110 и 117 соответственно)
Дальше идет вариант с регулярными выражениями (154 тика), вариант orefkov'а (187 тиков), вариант Пуделя (551 тик). Остальные варианты пока не померил.

(84) с регулярами заметь, можно весь тект за один присест, не построчно, "рассортировать".

(84) Блин, ты просто моё время с временем Сообщить замерял :))). Я только что проверил - у меня быстрее орефкова (моё 0.004647, орефкова 0.004695)

(84) Попробуй вариант для регулярных не по одной строке, а по "тексту" т.е. строке разделенной "РазделительСтрок". Если конечно в условия задачи вползает.

Да с Шаблон медленно когда не число зато код простой, можна и еще просче :)
.

(88) Не-а. Правда твой код я переписал, оставил только идею:
(87) Надо "тестовый стенд" для этого переписывать. Сейчас он выглядит так:
1. Исходные данные живут в дбф. 10000 строк. Строки формировались так:
1.1. Случайная длина строки от 1 до 40
1.2. Каждый символ строки генерировался случайным образом из набора "01234567890.,AB". Такой набор получил опытным путем - меня устроил процент "правильных" чисел:

15% (точнее - 1360 из 10000)
1.3. Массив строк хранится в глобальной переменной и перед началом работы считывается из dbf
2. Все алгоритмы загонялись в функцию, возвращающую количество чисел в наборе. Шаблон функции:

(84) ну, с учётом что исходные строки длиной <40, и что ограничение на дробную часть в 20 знаков.
можно добавить Лев(Стр,20) и Прав(Стр,20)

Читайте также: