(16)
1С. Общие требования к построению конструкций встроенного языка:
1. В конструкциях встроенного языка ключевые слова пишутся канонически (как в документации или Синтакс-помощнике).
Правильно:
КонецЕсли
Неправильно:
конецЕсли, КОНЕЦЕСЛИ, конецесли, Конецесли.
2. При следовании друг за другом нескольких операторов присваивания, допускается выравнивать их следующим образом:
ДиалогВыбора.ПолноеИмяФайла = ИмяФайла;
ДиалогВыбора.Каталог = ИмяПути; (тут должно быть выровнено по "=", но пробелы стираются при добавлении коммента)
Если не соблюдать эти 2 простых правила, то код будет резать глаза.
(18) Глупости.
Возможно Вы один из тех людей, что следуют дзен-правилам 1с и дорожат сертификатами, но не все таковыми являются.
То что 1с хочет навязать PascalCase не делает людей использующих camelCase неполноценными.
1) Я, например, оформляю код так и не вижу в нем ничего плохого и нечитабельного:
ПОКА А ЦИКЛ // <== Корневой цикл/условие с вложенными циклами/условиями обозначаю строчными
Для Каждого Б Из В Цикл
Если Г Тогда
мФруктов = СтрРазделить("Яблоки,Апельсины,Мандарины", ",");
КонецЕсли; // Если Г
КонецЦикла; // Для Каждого Б Из В
КОНЕЦЦИКЛА; // ПОКА А
Показать
Если работодатель будет против - буду делать в соответсвии корпоративным нормативом (ну или уволюсь).
2) Табуляции это, конечно, здорово, сам их использую на винде.
Только вот под линем они могут пойти по огромной такой [3,14]зде и выглядеть будет крайне отвратно.
Вы же доподлино не знаете под какой платформой сидит человек для подобных суждений, верно?
Алсо, на инфостарте табуляции в кодбоксе также отображаются криво, оценить можете в сниппетах под спойлерами всю плачевность ситуации: ТЫК
ВЫВОД: не стоит быть столь категоричным и плясать под дудку 1с.
Все же главное читабельность. А агрессивные работодатели с еб@нутыми требованиями/придирками получат соответсвующих специалистов.
БОНУС: В школах-институтах нас по рукам за GOTO били, так может теперь и Перейти (GOTO) не использовать?
Давненько не видел в чужих публикациях этого оператора, хотя его можно очень толково применять.
(19)
Я не следую всем правилам, просто когда все в едином стиле - это воспринимается лучше зрительно и говорит о том, что программист писал не на отъе***, а старался.
Зачем вы тогда по-русски пишете сейчас без ошибок, со знаками препинания, и предложения начинаете с большой буквы?
ДиалогВыбора.ПолноеИмяФайла = ИмяФайла;
ДиалогВыбора.Каталог = ИмяПути; (тут должно быть выровнено по "=", но пробелы стираются при добавлении коммента)
Отнюдь не "должно", хотя и красиво выглядит. И есть довольно много противников такого выравнивания (я лично к ним не отношусь).
(22)
Во-первых выглядит симпатичнее, а во-вторых сразу понятно, что это блок заполнения какой-то структуры.
Т.е. если тебе нужно что-то исправить, не относящееся к этому, можно много строк просто пропустить глазами, что ускоряет восприятие "чужого" кода, да и своего тоже.
Только вот под линем они могут пойти по огромной такой [3,14]зде и выглядеть будет крайне отвратно.
Алсо, на инфостарте табуляции в кодбоксе также отображаются криво
Во-первых выглядит симпатичнее, а во-вторых сразу понятно, что это блок заполнения какой-то структуры.
Т.е. если тебе нужно что-то исправить, не относящееся к этому, можно много строк просто пропустить глазами, что ускоряет восприятие "чужого" кода, да и своего тоже.
Но есть жесткие противники этого. На партнерке даже мини-холивар был по поводу "выравнивания". Раньше в Рекомендациях 1С по оформлению кода был этот пункт, а сейчас убрали вроде.
И, возможно, я ошибаюсь, но нам необходимо проверить делится ли число на 2, 3, 5 или 7.
Если не делится, значит оно - простое.
Соответственно, как то так:
На вход пусть подается ТЗ ТаблицаЧисел
Функция КоличествоПростыхВТаблице(ТаблицаЧисел)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Числа.Число
|ПОМЕСТИТЬ вт_Числа
|ИЗ
| &Числа КАК Числа
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| вт_Числа.Число,
| ВЫРАЗИТЬ(вт_Числа.Число / 2 КАК ЧИСЛО(15, 0)) КАК ДелениеНа2,
| вт_Числа.Число / 2 КАК ДелениеНа2СОстатком,
| ВЫРАЗИТЬ(вт_Числа.Число / 3 КАК ЧИСЛО(15, 0)) КАК ДелениеНа3,
| вт_Числа.Число / 3 КАК ДелениеНа3СОстатком,
| ВЫРАЗИТЬ(вт_Числа.Число / 5 КАК ЧИСЛО(15, 0)) КАК ДелениеНа5,
| вт_Числа.Число / 5 КАК ДелениеНа5СОстатком,
| ВЫРАЗИТЬ(вт_Числа.Число / 7 КАК ЧИСЛО(15, 0)) КАК ДелениеНа7,
| вт_Числа.Число / 7 КАК ДелениеНа7СОстатком
|ИЗ
| вт_Числа КАК вт_Числа
|ГДЕ
| (ВЫРАЗИТЬ(вт_Числа.Число / 2 КАК ЧИСЛО(15, 0))) <> вт_Числа.Число / 2
| И (ВЫРАЗИТЬ(вт_Числа.Число / 3 КАК ЧИСЛО(15, 0))) <> вт_Числа.Число / 3
| И (ВЫРАЗИТЬ(вт_Числа.Число / 5 КАК ЧИСЛО(15, 0))) <> вт_Числа.Число / 5
| И (ВЫРАЗИТЬ(вт_Числа.Число / 7 КАК ЧИСЛО(15, 0))) <> вт_Числа.Число / 7";
Запрос.УстановитьПараметр("Числа", ТаблицаЧисел);
Выборка = Запрос.Выполнить().Выбрать();
Возврат Выборка.Количество();
КонецФункции;
Вот такой запрос находит все нечетные простые числа на отрезке [1 ... 131073] за 1,308 сек. Используется решето Сундарама. Параметрами является N, которое задает интервал поиска как [1 ... 2N+1] и заранее вычисленное значение (SQRT(2N+1)-1)/2.
ВЫБРАТЬ
0 КАК Х
ПОМЕСТИТЬ Регистр1
ОБЪЕДИНИТЬ
ВЫБРАТЬ
1
;
ВЫБРАТЬ
Младшие.Х + 2 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр2
ИЗ
Регистр1 КАК Младшие,
Регистр1 КАК Старшие
;
ВЫБРАТЬ
Младшие.Х + 4 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр4
ИЗ
Регистр2 КАК Младшие,
Регистр2 КАК Старшие
;
ВЫБРАТЬ
Младшие.Х + 16 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр8
ИЗ
Регистр4 КАК Младшие,
Регистр4 КАК Старшие
;
ВЫБРАТЬ
Младшие.Х + 256 * Старшие.Х + 1 КАК Х
ПОМЕСТИТЬ Регистр16
ИЗ
Регистр8 КАК Младшие,
Регистр8 КАК Старшие
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
2 * ВложенныйЗапрос.Х + 1 КАК ПростоеЧисло
ИЗ
(ВЫБРАТЬ
А.Х + Б.Х + 2 * А.Х * Б.Х КАК Х
ИЗ
Регистр16 КАК А
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Регистр16 КАК Б
ПО (Б.Х МЕЖДУ А.Х И (&Эн - А.Х) / (2 * А.Х + 1))
ГДЕ
А.Х <= &КореньИз_ДваЭнПлюс1_Минус1_РазделитьНа2
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
А.Х
ИЗ
Регистр16 КАК А
ГДЕ
А.Х <= &Эн) КАК ВложенныйЗапрос
СГРУППИРОВАТЬ ПО
ВложенныйЗапрос.Х
ИМЕЮЩИЕ
КОЛИЧЕСТВО(*) = 1
УПОРЯДОЧИТЬ ПО
ПростоеЧисло
Показать
Первая часть запроса, формирующая ряд чисел, взята отсюда: Порождающий запрос. "Все нечетные простые числа" означает, что к результату (к полученному множеству простых чисел) нужно добавить единственное простое четное число 2.
(0) Понял, наконец, что меня смущает в варианте 2. Вся эта возня с квадратами ни к чему. Достаточно добавить поле ХХ (квадрат) к таблице чисел, что можно сделать (кажется) прямо при чтении таблицы в запрос. Тогда весь необходимый код уложится в минимум строк:
ВЫБРАТЬ
Числа.НатуральноеЧисло КАК Х,
Числа.НатуральноеЧисло * Числа.НатуральноеЧисло КАК ХХ
ПОМЕСТИТЬ ВТ
ИЗ
&Числа КАК Числа
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Делимое.Х КАК ПростоеЧисло
ИЗ
ВТ КАК Делимое
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ КАК Делитель
ПО Делимое.Х >= Делитель.ХХ
И ((ВЫРАЗИТЬ(Делимое.Х / Делитель.Х КАК ЧИСЛО(19, 0))) = Делимое.Х / Делитель.Х)
СГРУППИРОВАТЬ ПО
Делимое.Х
ИМЕЮЩИЕ
КОЛИЧЕСТВО(*) = 1
Показать
Условие делимости так написано нарочно, в надежде на то, что Делимое.Х / Делитель.Х будет вычисляться один раз.
Интересное упражнение. Поколдовал в конфегураторе и что-то такое получилось:
Запрос = Новый Запрос(
"ВЫБРАТЬ
| 0 КАК Поле1
|ПОМЕСТИТЬ ВТ1
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| 1
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| 2
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| 3
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ.Поле1 + ВТ1.Поле1 * 4 + ВТ2.Поле1 * 16 + ВТ3.Поле1 * 64 + ВТ4.Поле1 * 256 + 2 КАК Число
|ПОМЕСТИТЬ ВТСт
|ИЗ
| ВТ1 КАК ВТ,
| ВТ1 КАК ВТ1,
| ВТ1 КАК ВТ2,
| ВТ1 КАК ВТ3,
| ВТ1 КАК ВТ4
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ РАЗЛИЧНЫЕ
| ВТК.Число * ВТСт.Число КАК Число
|ПОМЕСТИТЬ ВТНеПростые
|ИЗ
| ВТСт КАК ВТСт,
| ВТСт КАК ВТК
|ГДЕ
| ВТК.Число * ВТСт.Число < &Предел
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТСт.Число КАК Число
|ИЗ
| ВТСт КАК ВТСт
|ГДЕ
| ВТСт.Число < &Предел И НЕ ВТСт.Число В
| (ВЫБРАТЬ
| ВТНеПростые.Число
| ИЗ
| ВТНеПростые)
|
|
|УПОРЯДОЧИТЬ ПО
| ВТСт.Число");
Запрос.УстановитьПараметр("Предел", Предел);
Таблица.Загрузить(
Запрос.Выполнить().Выгрузить()
);
Показать
Кстати, этот запрос легко модицифировать и получить все натуральные делители для нужного числа, а кто-то тут не так давно отказывался от решения подобной задачи на собеседовании )))
У меня тоже решето Аткина проигрывает решету Сундарама. Вот моя реализация:
ВЫБРАТЬ
0 КАК Х
ПОМЕСТИТЬ Регистр1
ОБЪЕДИНИТЬ
ВЫБРАТЬ
1
;
ВЫБРАТЬ
Младшие.Х + 2 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр2
ИЗ
Регистр1 КАК Младшие,
Регистр1 КАК Старшие
;
ВЫБРАТЬ
Младшие.Х + 4 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр4
ИЗ
Регистр2 КАК Младшие,
Регистр2 КАК Старшие
;
ВЫБРАТЬ
Младшие.Х + 16 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр8
ИЗ
Регистр4 КАК Младшие,
Регистр4 КАК Старшие
;
ВЫБРАТЬ
1 + Младшие.Х + 256 * Старшие.Х КАК Х
ПОМЕСТИТЬ Ряд
ИЗ
Регистр8 КАК Младшие,
Регистр2 КАК Старшие
ГДЕ
1 + Младшие.Х + 256 * Старшие.Х <= &КореньИзГраницы
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
КвадратичныеФормы.Х,
КвадратичныеФормы.Х * КвадратичныеФормы.Х КАК ХХ
ПОМЕСТИТЬ Кандидаты
ИЗ
(ВЫБРАТЬ
Случай1.Х КАК Х
ИЗ
(ВЫБРАТЬ
4 * А.Х * А.Х + Б.Х * Б.Х КАК Х
ИЗ
Ряд КАК А,
Ряд КАК Б) КАК Случай1
ГДЕ
СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, Случай1.Х * 5)) В (5, 25)
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Случай2.Х
ИЗ
(ВЫБРАТЬ
3 * А.Х * А.Х + Б.Х * Б.Х КАК Х
ИЗ
Ряд КАК А,
Ряд КАК Б) КАК Случай2
ГДЕ
СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, Случай2.Х * 5)) = 35
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Случай3.Х
ИЗ
(ВЫБРАТЬ
3 * А.Х * А.Х - Б.Х * Б.Х КАК Х
ИЗ
Ряд КАК А
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Ряд КАК Б
ПО А.Х > Б.Х) КАК Случай3
ГДЕ
СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, Случай3.Х * 5)) = 55) КАК КвадратичныеФормы
ГДЕ
СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, КвадратичныеФормы.Х * 12)) > 0
И КвадратичныеФормы.Х <= &Граница
СГРУППИРОВАТЬ ПО
КвадратичныеФормы.Х
ИМЕЮЩИЕ
СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, КОЛИЧЕСТВО(*) * 30)) = 30
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Делимое.Х КАК Х
ИЗ
Кандидаты КАК Делимое
ЛЕВОЕ СОЕДИНЕНИЕ Кандидаты КАК Делитель
ПО (Делитель.ХХ <= Делимое.Х)
И ((ВЫРАЗИТЬ(Делимое.Х / Делитель.Х КАК ЧИСЛО(15, 0))) = Делимое.Х / Делитель.Х)
ГДЕ
Делитель.Х ЕСТЬ NULL
ОБЪЕДИНИТЬ
ВЫБРАТЬ
2
ОБЪЕДИНИТЬ
ВЫБРАТЬ
3
ОБЪЕДИНИТЬ
ВЫБРАТЬ
5
УПОРЯДОЧИТЬ ПО
Делимое.Х
Показать
для сравнения. Тут вроде бы нечего дальше оптимизировать, а работает примерно в 1,6 раза дольше, чем Сундарама, который еще можно чуть-чуть "подкрутить" в плане оптимизации (за счет проверки пустых мест рядом с четными, а не соединением с таблицей чисел). Это странно. Алгоритм Аткина вообще-то считается более быстрым.
(31) Да, но и с секундами будет когда-нибудь ругаться. Там предел 2^32 - 1 или 2^31 - 1. Это примерно миллиард. Надеюсь, никто не додумается из миллиарда простые числа в запросе определять. Так как будет уже не с временем (оно почти линейно растет, поэтому миллиард за 16000 секунд должен посчитаться), а с памятью проблемы.