Битовые операции

23.07.14

Разработка - Универсальные функции

Пример того, как можно вызывать битовые операции из 1С
Занимаясь программой для поиска решений головоломки Bedlam Cube, я задался вопросом, а можно ли в 1С реализовать битовые операции. Дело в том, что кубик, который надо собрать, имеет размеры 4х4х4. А значит его можно описать с помощью 64-х разрядного числа, в котором каждый бит соответствует ячейке (клетке) головоломки. В 1С числа представляются в виде строк и , как следствие, операций над битами нет. Но побитовые операции есть в Transaq-SQL (& - побитовое И, | - побитовое ИЛИ, ^ -  побитовое исключающее ИЛИ). Среди типов данных, которые входят в стандарт языка Transaq-SQL присутствует bigint, которое имеет длину 8 байт, что и соответствует 64-х разрядному числу. Сначала я создал хранимые процедуры, с помощью которых выполняются побитовые операции. Ниже приведен пример одной из них.

CREATE PROCEDURE [dbo].[BitOR]

-- Add the parameters for the stored procedure here
@BigInt1 bigint,
@BigInt2 bigint
AS
BEGIN
 SET NOCOUNT ON;
 SELECT @BigInt1 | @BigInt2
END

Аналогично можно реализовать две оставшиеся операции. Теперь покажем как организовать вызов данных процедур из 1С. Для этого нам потребуется подключение к SQL серверу.
Функция глSQLПодключение() Экспорт
SQLConnect = Новый COMОбъект("ADODB.Connection"); 
ConnectionString = "driver={SQL Server}; server=<Имя сервера>; uid=<Имя пользователя>; pwd=*******; DataBase=<Имя базы> ";
SQLConnect.ConnectionTimeOut =600;SQLConnect.CursorLocation = 3;
попытка
SQLConnect.Open(ConnectionString);
исключение
SQLConnect="";
Предупреждение("Невозможно установить соединение");
возврат Неопределено;
конецпопытки;
возврат SQLConnect;
КонецФункции
Приведенная функция в случае успешного завершения возвращает com-объект, который позволяет выполнять команды на SQL сервере. Используя созданное подключение, мы можем вызвать хранимую процедуру. Ниже пример того, как это сделать из 1С.
Функция BitOr(вхЧсл1,вхЧсл2,вхSQLConnect)
CmdSQL = Новый COMОбъект("ADODB.Command")    ;
CmdSQL.ActiveConnection = вхSQLConnect       ;   
CmdSQL.CommandText = "EXEC [dbo].[BitOr] "+Формат(вхЧсл1,"ЧН=0; ЧГ=0")+","+Формат(вхЧсл2,"ЧН=0; ЧГ=0");
rs=CmdSQL.Execute();
rs.MoveFirst();
возврат rs.Fields(0).Value;
КонецФункции
Теперь поговорим о том, как получить текущее состояние кубика. В 1С реализованы длинное умножение и сложение, а длина данных, с которыми можно оперировать, определяется исключительно размером доступной памяти. Поэтому получить массив, в котором хранятся значения степеней двойки для значений показателя от 0 до 63, труда не составляет. Далее каждой  точке с координатами x,y и z  мы можем сопоставить число из диапазона 0...63. Это число рассчитывается по формуле z+4*(y+4*x). После этого, чтобы получить состояние,описывающее наш кубик, мы должны для каждой заполненной точки вычислить ее положение в одномерном массиве, найти значение двойки в данной степени и полученные числа сложить. Все просто и понятно. Но тип данных bigint хранит данные в диапазоне (-2^63) до (2^63-1), а значит при попытке передать в хранимую процедуру число 2^63 мы получим ошибку. Нам надо понять какому значению соответствует двоичная запись, которая содержит 0 во всех разрядах, кроме самого старшего. Для этого надо найти информацию о представлении в памяти целых отрицательных чисел. Это не сложно. Алгоритм следующий, надо взять двоичную запись положительного числа, инвертировать ее, то есть 0 заменить на 1, а 1 на 0, затем к получившемуся числу прибавить 1. Используя полученные сведения, найдем представление для (-1):
  1. Двоичная запись 1 - 0x000...001
  2. Инвертируем 0x111...110
  3. Прибавляем 1, получаем 0x111...111
Вспоминаем, что двоичная запись для (2^63 -1) это 0x011...111 ( единица во всех разрядах кроме старшего). Ну и последний шаг, вычтем из двоичного представления для (-1) двоичное представление для (2^63 -1), получим 0x100...000. Таким образом, когда нам надо заполнить самый старший бит в двоичном представлении нашего куба, мы должны к числу, описывающему текущее состояние, прибавить (-2^63). Что я и сделал. И это все заработало !
Поиск решения заключается в переборе всех возможных вариантов исходных элементов. Для этого я предварительно подготовил таблицу состояний, в которой  для каждой фигуры и каждого  положения фигуры вычислил ее характеристику, как это описано выше. Затем в процедуре поиска, когда мне нужно было проверить можно ли разместить фигуру в кубике, я вычислял логическое И между текущим состоянием и характеристикой фигуры и если оно равнялось нулю, то фигуру можно было разместить. Поставить фигуру - вычислить логическое ИЛИ между текущим состоянием и характеристикой фигуры, снять фигуру - вычислить логическое ИСКЛЮЧАЮЩЕЕ ИЛИ  между текущим состоянием и характеристикой фигуры. Разумеется, изложенную методику я реализовал, как дополнительную к более простой, когда состояние кубика описывалось трехмерным массивом.
Ну и ответ на вопрос, зачем это надо. Человеческий мозг содержит около 86 млрд. нейронов, но не это количество делает его поистине уникальным. Значительно важнее связи между нейронами, а вот здесь количество сочетаний становится просто астрономическим. Возможно, прочитав эту статью, у вас сложится неожиданная цепочка, которая впоследствии приведет к решению задачи, весьма далекой от изложенной. 




битовые операции TRANSAQ-SQL

См. также

Универсальные функции Программист Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.

21.05.2024    25104    dimanich70    82    

149

Универсальные функции Программист Платформа 1С v8.3 1C:Бухгалтерия Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    4504    3    John_d    11    

57

Универсальные функции Программист Стажер Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    25396    atdonya    25    

58

Универсальные функции Программист Платформа 1С v8.3 Бесплатно (free)

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

30.11.2023    6071    ke.92@mail.ru    17    

65

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    16542    YA_418728146    8    

170

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    4262    73    progmaster    10    

4

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 1C:Бухгалтерия 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    19135    180    sapervodichka    112    

136
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. viollan 30.07.14 11:47 Сейчас в теме
Прошу прощения, но заголовок статьи не соответствует содержанию. Вы выполняете побитовые операции не на 1С, а на SQL. С таким успехом можно выполнить эти действия используя .Net, ВК и пр.
2. scientes 296 30.07.14 12:36 Сейчас в теме
Благодарю за замечание, внес исправления в анонс статьи.
3. kg_am 178 01.08.14 12:42 Сейчас в теме
Что-то мне подсказывает, что вызов CmdSQL.Execute() будет происходить по-любому на порядок дольше, чем если средствами языка 1С перевести числа в двоичную систему и сделать всё, что нужно.
4. scientes 296 04.08.14 14:21 Сейчас в теме
Вы правы, решение с обращением к SQL серверу увеличивает время расчета, и чем больше перебирается вариантов, тем больше это различие. Я и не говорю, что предложенный способ лучше. Он рабочий, это верно.
5. kg_am 178 05.08.14 20:07 Сейчас в теме
У меня получилась такая функция побитового "или":

Функция BitOr(вхЧсл1, вхЧсл2)
	ОстатокЧ1 = вхЧсл1;
	ОстатокЧ2 = вхЧсл2;
	Множитель = 1;
	Результат = 0;
	Пока ОстатокЧ1 <> 0 и ОстатокЧ2 <> 0 Цикл
		Результат = Результат + Макс(ОстатокЧ1 % 2, ОстатокЧ2 % 2) * Множитель;
		ОстатокЧ1 = Цел(ОстатокЧ1 / 2);
		ОстатокЧ2 = Цел(ОстатокЧ2 / 2);
		Множитель = Множитель * 2;
	КонецЦикла;
	Возврат Результат + (ОстатокЧ1 + ОстатокЧ2) * Множитель;
КонецФункции
Показать


Дёшево и сердито. Главное - быстро.
Оставьте свое сообщение