Как поменять значение двух переменных, не используя третью в 1С

Недавно мой старый знакомый посетовал на то, что не смог пройти собеседование на должность 1С программист.  Узнав, что у него спрашивали, я задумался. Что и говорить, в его ситуации растерялся бы и я. Хотя ничего страшного в заданиях нет. Просто как-то необычно, что спрашивают алгоритмы вместо прикладных объектов.

Задача поменять местами значения переменных часто встречается при программировании. Например, без нее не обходится алгоритмы сортировки. Однако там часто используется третья буферная переменная. На С++ это будет выглядеть так:

int a=3,b=5,buf; 
buf=a;
a=b;
b=buf;

Значения поменялись. Задача выполнена. Так рекомендуется делать. Однако есть и другие способы. Один из моих любимых это использование xor (можете ознакомиться с ним в уроках по другим языкам программирования, например по С++).

Этот метод изящен и непонятен на первый взгляд. Кроме того, исключающий ИЛИ значительно медленнее обычного свопирования (обмена) переменных через буфер.

Давайте теперь поменяем значения xorом наших переменных a и b:

int a=3, b=5;
a^=b^=a^=b;
cout<<a<<endl<<b;

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

Все хорошо, однако в 1С нет xor. Разработчики решили, что он там не нужен. Ну и бог с ним. Решим другим способом.

a=3;

b=5;

a=a+b;

b=a-b;// здесь уже будет 3

a=a-b; // а теперь равно 5

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

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

Я же, в свою очередь, в этом блоге постараюсь разобрать для вас всевозможные каверзные вопросы.

Вячеслав Головлев.


Комментарии

11 комментариев на “Как поменять значение двух переменных, не используя третью в 1С”
  1. Александр:

    эти способы верны только для числовых переменных. Вот вариант для переменных произвольных типов на сях:

    int main()
    {
    char *a = «test1»;
    char *b = «test2»;
    a += 2 * (b-a);
    b -= (a-b);
    a -= (a-b) / 2;
    printf(«%s and %s», a, b);
    }

  2. admin:

    Спасибо за напоминание! Мне почему-то пришло в голову, что обычно просят поменять значение только числовых переменных. О произвольных я как-то забыл. Ваш способ я знаю, но тем не менее, спасибо за поправку.
    В 1С своя специфика работы и к его синтаксису не так легко приловчиться. Описанный вами способ там по-просту бесполезен, так как система приведет значение к числовому типу.

  3. Знаток:

    int main()
    {
    char *a = «test1″;
    char *b = «test2″;
    a += 2 * (b-a);
    b = 2*b-a; //раскрыть скобки они здесь в прицепе не надо
    a -= (a-b) / 2;
    printf(«%s and %s», a, b);
    }
    а так вариант крутой, респект за работу с адресами мало их кто хорошо понимает.

  4. Знаток:

    К примеру если тип вести максимальное числовое значения
    a=3;
    b=5;
    a=a+b;
    b=a-b;// здесь уже будет 3
    a=a-b; // а теперь равно 5

    недостаток что существует ограничения по целым числам на скок мне известно в 32 знака.И может возникнуть переполнения к примеру если a=999…и так всего 32 знака ,b=888…и так тоже 32 знака,a=a+b даст не их суму так как это уже будет 33 знака.(по идеи даст 0 или ошибку).

    • admin:

      Уважаемый Знаток! Все верно, но только не забывайте, что статья писалась об 1С! Там этих ограничений просто нет.
      Если бы я писал о сях или моей любимой жабе, то материал бы был совершенно другой

      • Знаток:

        Ограничения есть всегда)Другое дело что таковы значения вряд ли будут использоваться.
        Я писал за ограничения в 1с(может быть не совсем правильно так как не пользуюсь им).

        • admin:

          Ладно, пусть реализация в 1С лежит на совести Нуралиева ))) В любом случае, всегда приятно подискутировать со специалистами)))
          Знаете, если я доберусь до написания статей, то выложу ряд материала по реверсивной инженерии. В частности, так как я последний год работаю на дойчей питонщиком, то хотелось бы показать простой дебаггер на питоне.
          А вот там пригодятся и все Ваши знания в области регистров процессора, реализации компиляторов для той или иной платформы (кстати, не хотите со мной поспорить, что ассемблер интерпретирующий язык?)
          В любом случае, спасибо за поправки. Действительно приятно видеть читателя, который задумывается о написанном.

          • Знаток:

            Спасибо.Спорить не буду, так как плотно с Ассемблером не знаком. В вот что связанно с С, С++, С#, VBasic, JavaScript пожалуйста)

  5. Александр:

    void main()
    {
    char *a = «test1»;
    char *b = «test2»;
    a += 2*(b-a);
    b -= (a-b);
    a -= (a-b)/2 ;
    printf(«%s and %s», a, b);
    }

    скажите пожалуйста для чего здесь умножить а потом делить на 2, и почему если написать как в случае с числами a += a+b , то это считается ошибкой?

  6. Owl Hex:

    a=2
    b=3
    a=a+b (2+3=5)
    b=a-b (5-3=2)
    a=a-b (5-2=3)
    (a=3, b=2)

  7. Николай:

    Если вы не против — добавлю еще один вариант)
    Если возникают ограничения с использованием памяти, удобнее уменьшить промежуточное число(небольшая погрешность, как правило, автоматически убирается):

    a = 4;
    b = 6;

    a = a / b; (4 / 6 = 0,666666666666666667)
    b = a * b; (0,666666666666666667 * 6 = 4)
    a = b / a; (4 / 0,666666666666666667 = 6)

    // a = 6, b = 4

Добавить комментарий

Внимание! Не будут добавляться комментарии в виде откровенного спама или прямого анкора на свои сайты. Все спамеры будут передаваться в базу Akismet

Подтвердите, что Вы не бот — выберите человечка с поднятой рукой: