Jason. Cała informatyka w jednym miejscu!

Dawno nie było żadnego artykułu na temat samego programowania więc macie ode mnie kolejny wpis dotyczący tym razem prostej rzeczy, którą można wykonać na kilka sposobów zarówno klasycznie, jak i wyjątkowo. Chodzi mi o często spotykany manewr jakim jest zamiana wartości dwóch zmiennych. Zdecydowana większość posługuje się metodą polegającą na użyciu zmiennej tymczasowej (pomocniczej) do tymczasowego przechowania jednej z dwóch liczb tuż przed operacją zamiany. To jak najbardziej logiczne podejście, bo podczas zamiany trzeba gdzieś przechować na chwilę jedną z dwóch wartości. Czy rzeczywiście to jest konieczne?

ZAMIANA WARTOŚCI DWÓCH ZMIENNYCH METODĄ KLASYCZNĄ

Na sam początek w ramach przypomnienia i zobrazowania całej sytuacji zademonstruję jak wykonać zamianę tradycyjnie posługując się dodatkową zmienną robiącą za "schowek". Oto kod źródłowy w języku C. Pozwoliłem sobie wykorzystać przekazywanie przez referencje:

#include <stdio.h>

void printNumbers(int a, int b);
void swap(int *a, int *b);

int main(void)
{
	int a = 32;
	int b = 60;

	printNumbers(a, b);
	swap(&a, &b);
	printNumbers(a, b);
	
	return 0;
}

void printNumbers(int a, int b)
{
	printf("A = %d\n", a);
	printf("B = %d\n", b);
	printf("======\n");
}

void swap(int *a, int *b)
{
	int temp = *b;

	*b = *a;
	*a = temp;
}

Zachęcam do skompilowania sobie tego programu. Przyglądając się definicji funkcji "swap" mamy w środku zmienną lokalną "temp", która stanowi konieczność jeśli zamiana wartości dwóch zmiennych ma zostać wykonana. Określam to "tradycyjną" metodą, gdyż postąpi tak każdy początkujący nieznający innych metod pozwalających na uniknięcie przechowywania wartości gdzieś na uboczu. A są jeszcze inne sposoby niewymagające zmiennej "słupa".

METODY BEZ UŻYWANIA OSOBNEJ ZMIENNEJ

Skoro już kojarzycie ten zapis i jego zastosowanie, to teraz zaprezentuję Wam kilka sposobów jak wykonać to samo bez żadnych zmiennych pomocniczych. Zaznaczam jednak na sam początek, że w artykule tym operuję na liczbach całkowitych i poniższe metody mogą się nie sprawdzić na liczbach zmiennoprzecinkowych z powodu innego sposobu przechowywania w pamięci komputera! Oto wszystkie sposoby jakie znam:

KORZYSTAJĄC Z ALTERNATYWY WYKLUCZAJĄCEJ "XOR"

"XOR" (ang. "exclusive OR") to jeden z tzw. "funktorów zdaniotwórczych" stający się prawdziwy wtedy i tylko wtedy, gdy TYLKO JEDNO zdanie jest prawdziwe. Korzystając z poprzedniej ramki z kodem, nasza funkcja "swap" wyglądałaby tak:

void swap(int *a, int *b)
{
	*a ^= *b;
	*b ^= *a;
	*a ^= *b;
}

Po skompilowaniu powyższej funkcji, obie liczby zostaną zamienione. Dzieje się tak w wyniku przeprowadzenia obliczeń alternatywy wykluczającej. Weźmy sobie te same liczby zmiennych:

a = 32, b = 60

Zamieniając liczby na system binarny otrzymujemy:

a = 100000(bin), b = 111100(bin)

Po konwersji wykonywane jest obliczanie "XOR" pod kreską:

a 1 0 0 0 0 0
b 1 1 1 1 0 0
a^b 0 1 1 1 0 0

Zamiana wartości dwóch zmiennych odbywa się poprzez przypisywanie wyniku do zmiennej, w tym przypadku do zmiennej "a". Tak wygląda drugi krok:

b 1 1 1 1 0 0
a 0 1 1 1 0 0
b^a 1 0 0 0 0 0

Otrzymywany wynik jest przypisywany do zmiennej "b". Czy to nie jest ten sam wynik, który występował wcześniej w zmiennej "a"? Tak jest! Na samym końcu powtarzamy ten sam krok co na początku, zatem:

a 0 1 1 1 0 0
b 1 0 0 0 0 0
a^b 1 1 1 1 0 0

Wynik "XOR" przypisuje się do zmiennej "a". Po tych operacjach, zamiana wartości dwóch zmiennych zostaje zakończona i liczby są zamienione miejscami bez korzystania z osobnej "przechowalni".

Alternatywa wykluczająca

Alternatywa wykluczająca zwraca prawdę wyłącznie gdy NIEPARZYSTA liczba zdań jest PRAWDZIWA.

Źródło: Wikimedia

KORZYSTAJĄC Z DODAWANIA I ODEJMOWANIA

Jeśli powyższa metoda jest zbyt trudna do zrozumienia, to możecie to zrobić jeszcze za pomocą dodawania i odejmowania tych liczb od siebie. Najpierw kod źródłowy:

void swap(int *a, int *b)
{
	*a += *b;
	*b = *a - *b;
	*a -= *b;
}

Tu nie ma wymagania rozpisywania się tak szczegółowo. Wystarczy prawidłowo ułożyć równanie w postaci sumy i różnicy oraz powstawiać we właściwe miejsca.

KORZYSTAJĄC Z MNOŻENIA I DZIELENIA

Zostaje jeszcze opcja połączenia iloczynów i ilorazów. Zamiana wartości dwóch zmiennych odbywa się bardzo podobnie w porównaniu do poprzedniego sposobu z tym, że zamiast dodawania mamy mnożenie, a zamiast odejmowania, dzielenie. Oto definicja funkcji:

void swap(int *a, int *b)
{
	*a *= *b;
	*b = *a / *b;
	*a /= *b;
}

I tym razem obejdzie się bez szerszego opisywania.


Po przedstawieniu takiego "kawałka" wiedzy, zamykam temat jak wygląda zamiana wartości dwóch zmiennych bez korzystania ze zmiennej pobocznej. Informuję na końcu, iż opanowanie tych zapisów nie jest wyłącznie "sztuką dla sztuki", ale również jest pozytywnie postrzegane w Waszych kodach źródłowych korzystających z zamiany bez dodatkowych zmiennych.

PODOBNE ARTYKUŁY