Свопинг двух значений переменной, не используя третью переменную

Комментируя

  • Ctrl + K , Ctrl + C - Комментарий текущий объект

  • Ctrl + K , Ctrl + U - Некомментарий текущий объект

большая вещь об этом состоит в том, что это относится к элементу, в котором Вы в настоящее время находитесь - Вы не должны выбирать целую строку кода VB для комментария его, например, Вы просто вводите Ctrl + K , Ctrl + C для комментария текущей строки. На aspx странице можно прокомментировать большой блок кода - например, всего ListView - просто идя в первую строку и поражая Ctrl + K , Ctrl + C .

97
задан 5377037 6 July 2017 в 16:04
поделиться

6 ответов

Использование алгоритма обмена xor

void xorSwap (int* x, int* y) {
    if (x != y) { //ensure that memory locations are different
       *x ^= *y;
       *y ^= *x;
       *x ^= *y;
    }
}


Зачем нужен тест?

Тест должен гарантировать, что x и y имеют разные ячейки памяти (а не разные значения) . Это потому, что (p xor p) = 0 , и если и x, и y используют одну и ту же ячейку памяти, когда один установлен в 0, оба устанавливаются в 0. Когда и * x, и * y равны 0, все остальные операции xor для * x и * y будут равны 0 (поскольку они одинаковы), что означает, что функция установит для * x и * y значение 0.

Если у них одинаковые значения, но не одно и то же место в памяти, все работает, как ожидалось

*x = 0011
*y = 0011
//Note, x and y do not share an address. x != y

*x = *x xor *y  //*x = 0011 xor 0011
//So *x is 0000

*y = *x xor *y  //*y = 0000 xor 0011
//So *y is 0011

*x = *x xor *y  //*x = 0000 xor 0011
//So *x is 0011


Следует ли это использовать?

В общих случаях нет. Компилятор оптимизирует временную переменную и, учитывая, что замена является обычной процедурой, он должен выводить оптимальный машинный код для вашей платформы.

Возьмем, к примеру, эту программу быстрой проверки, написанную на C.

#include <stdlib.h>
#include <math.h>

#define USE_XOR 

void xorSwap(int* x, int *y){
    if ( x != y ){
        *x ^= *y;
        *y ^= *x;
        *x ^= *y;
    }
}

void tempSwap(int* x, int* y){
    int t;
    t = *y;
    *y = *x;
    *x = t;
}


int main(int argc, char* argv[]){
    int x = 4;
    int y = 5;
    int z = pow(2,28); 
    while ( z-- ){
#       ifdef USE_XOR
            xorSwap(&x,&y);
#       else
            tempSwap(&x, &y);
#       endif
    }
    return x + y;    
}

Скомпилировано с использованием:

gcc -Os main.c -o swap

Версия xor принимает

real    0m2.068s
user    0m2.048s
sys  0m0.000s

, а версия с временной переменной принимает:

real    0m0.543s
user    0m0.540s
sys  0m0.000s
150
ответ дан 24 November 2019 в 05:19
поделиться
a = a + b
b = a - b // b = a
a = a - b
80
ответ дан 24 November 2019 в 05:19
поделиться

Глупые вопросы заслуживают соответствующих ответов:

void sw2ap(int& a, int& b) {
  register int temp = a; // !
  a = b;
  b = temp;
}

Единственное хорошее использование ключевого слова register .

10
ответ дан 24 November 2019 в 05:19
поделиться

Как уже отмечалось в manu, алгоритм XOR - популярный алгоритм, который работает для всех целочисленных значений (включая указатели, с некоторой удачей и приведением типов). Для полноты картины я хотел бы упомянуть еще один менее мощный алгоритм с добавлением / вычитанием:

A = A + B
B = A - B
A = A - B

Здесь нужно быть осторожным с переполнением / потерей данных, но в остальном он работает так же хорошо. Вы можете даже попробовать это с числами с плавающей запятой / удвоением, если XOR для них запрещен.

18
ответ дан 24 November 2019 в 05:19
поделиться

в общем виде:

A = A operation B
B = A inverse-operation B
A = A inverse-operation B 

, однако, вы должны потенциально остерегаться переполнения, а также не все операции имеют инверсию, которая хорошо определена для всех значений, для которых определена операция. например, * и / работают до тех пор, пока A или B не станут равными 0

xor особенно приятен, поскольку он определен для всех целых чисел и является собственным обратным

87
ответ дан 24 November 2019 в 05:19
поделиться

Никто еще не предлагал использовать std :: swap .

std::swap(a, b);

Я не использую никаких временных переменных и в зависимости от типа a и b реализация может иметь специализацию, которой также нет. Реализация должна быть написана с учетом того, уместен ли «трюк». Нет смысла делать второе предположение.

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

using std::swap;
swap(a, b);

Конечно, Реакция собеседника на такой ответ может многое сказать о вакансии.

77
ответ дан 24 November 2019 в 05:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: