Гид по технологиям

Как поменять местами два числа: 7 способов с примерами

• 5 min read • Программирование • Обновлено 29 Nov 2025
Как поменять местами два числа — 7 способов
Как поменять местами два числа — 7 способов

Плитка с числами на кнопках

Введение

Как программист, вы наверняка не раз сталкивались с задачей обмена значений двух переменных. Это одна из базовых операций, но у неё есть несколько реализаций с разными преимуществами и ограничениями. В этой статье мы рассмотрим основные подходы, их примеры на C++, Python и JavaScript, а также рекомендации, когда какой метод применять.

Определение: “обмен значений” — присвоение значения первой переменной второй и наоборот без потери данных.

Основные варианты (кратко)

  • Временная переменная — самый безопасный и понятный способ.
  • Арифметика (сложение/вычитание или умножение/деление) — экономит память, но риск переполнения и деления на ноль.
  • Битовые операции (XOR) — работает для целых типов, но снижает читаемость.
  • Однострочные трюки и распаковывание (tuple unpacking, std::swap) — доступны в некоторых языках и наиболее выразительны.

Как поменять местами два числа с помощью временной переменной

Это самый очевидный и безопасный способ. Алгоритм:

  1. temp = a
  2. a = b
  3. b = temp

Пример на C++:

#include 
using namespace std;

// Функция демонстрирует обмен и печатает результаты
void swapNums(int num1, int num2) {
    cout << "Before Swapping:" << endl;
    cout << "num1 = " << num1 << ", num2 = " << num2 << endl;

    int temp = num1;
    num1 = num2;
    num2 = temp;

    cout << "After Swapping:" << endl;
    cout << "num1 = " << num1 << ", num2 = " << num2 << endl;
}

int main() {
    swapNums(80, 50);
    return 0;
}

Пример на Python:

def swapNums(num1, num2):
    print("Before Swapping:")
    print("num1:", num1, ", num2:", num2)

    temp = num1
    num1 = num2
    num2 = temp

    print("After Swapping:")
    print("num1:", num1, ", num2:", num2)

swapNums(80, 50)

Пример на JavaScript:

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

Как поменять местами два числа с помощью арифметики (сложение/вычитание)

Идея: использовать сумму и разницу, чтобы извлечь исходные значения без дополнительной переменной.

Алгоритм:

  1. a = a + b
  2. b = a - b
  3. a = a - b

Пример на C++:

#include 
using namespace std;

void swapNums(int num1, int num2) {
    cout << "Before Swapping:" << endl;
    cout << "num1 = " << num1 << ", num2 = " << num2 << endl;

    num1 = num1 + num2;
    num2 = num1 - num2;
    num1 = num1 - num2;

    cout << "After Swapping:" << endl;
    cout << "num1 = " << num1 << ", num2 = " << num2 << endl;
}

int main() {
    swapNums(80, 50);
    return 0;
}

Пример на Python:

def swapNums(num1, num2):
    print("Before Swapping:")
    print("num1:", num1, ", num2:", num2)

    num1 = num1 + num2
    num2 = num1 - num2
    num1 = num1 - num2

    print("After Swapping:")
    print("num1:", num1, ", num2:", num2)

swapNums(80, 50)

Ограничения и предупреждения:

  • Риск переполнения при работе с фиксированной целочисленной арифметикой (например, int в C++).
  • Для чисел с плавающей точкой потеря точности.
  • Метод не применим, если типы не поддерживают арифметику.

Как поменять местами два числа с помощью арифметики (умножение/деление)

Алгоритм похож, но использует произведение и деление:

  1. a = a * b
  2. b = a / b
  3. a = a / b

Это НЕ рекомендуется в большинстве случаев:

  • Если одно из значений 0, вы получите потерю данных или деление на ноль.
  • Для целых типов возможны переполнения.

Используйте этот метод только если вы точно контролируете диапазоны и типы (например, фиксированные положительные числа и проверка на ноль).

Как поменять местами два числа с помощью битовых операций (XOR)

XOR-переброска работает для целых типов и не использует дополнительной переменной:

Алгоритм:

  1. a = a ^ b
  2. b = a ^ b
  3. a = a ^ b

Пример на C++:

#include 
using namespace std;

void swapNums(int num1, int num2) {
    cout << "Before Swapping:" << endl;
    cout << "num1 = " << num1 << ", num2 = " << num2 << endl;

    num1 = num1 ^ num2;
    num2 = num1 ^ num2;
    num1 = num1 ^ num2;

    cout << "After Swapping:" << endl;
    cout << "num1 = " << num1 << ", num2 = " << num2 << endl;
}

int main() {
    swapNums(80, 50);
    return 0;
}

Ограничения:

  • Работает только для целых типов (integers).
  • Если a и b ссылаются на один и тот же объект (алиасинг), то результат будет 0; избегайте использования на одном и том же адресе.
  • Читаемость хуже, чем у простого обмена с temp.

Однострочные и встроенные решения

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

Python (распаковка):

num1, num2 = num2, num1

C++ (std::swap):

#include 
std::swap(num1, num2);

JavaScript (деструктуризация):

[num1, num2] = [num2, num1];

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

Когда методы не работают или опасны (контрпримеры)

  • Арифметический обмен приведёт к переполнению на большом int и даст неправильный результат.
  • Умножение/деление ломается при нуле.
  • XOR-метод даёт неверный результат при том же адресе обеих переменных (например, при обмене элемента массива с самим собой).
  • В многопоточной среде простых обменов недостаточно: нужны атомарные операции или блокировки.

Important: для большинства приложений используйте явный обмен или встроенные функции swap — это снижает риск ошибок.

Практические рекомендации и эвристики

  • Читаемость важнее микрооптимизаций. Если не в профилируемом участке, используйте temp или std::swap.
  • Для целых типов и ограниченных ресурсов можно рассматривать XOR, но документируйте намерение.
  • Избегайте арифметических методов при неизвестных диапазонах входных данных.
  • В многопоточных сценариях используйте атомарные примитивы.

Факто-бокс

  • Память: все методы, кроме специально использующих temp, работают с O(1) дополнительной памяти.
  • Время: все методы выполняются за O(1) операций.
  • Риски: переполнение, деление на ноль, алиасинг.

Критерии приёмки

  • Код корректно меняет местами любые два входных значения соответствующего типа.
  • Нет неоправданных побочных эффектов (например, деление на ноль или изменение третьих переменных).
  • Решение читаемо и сопровождается тестами для граничных случаев.

Тесты и примеры для проверки

  • Обычные значения: (80, 50) -> (50, 80).
  • Одинаковые значения: (5, 5) -> (5, 5).
  • Ноль: (0, 5) для каждого метода проверяет деление/умножение.
  • Крайние целые: использовать максимально возможные значения для проверки переполнения.
  • Алиасинг: обмен a и a (или элемент массива с самим собой) для проверки XOR.

Чек-лист для ролей

  • Новичок: используйте временную переменную или распаковку (Python).
  • Опытный разработчик: используйте std::swap или деструктуризацию для компактности.
  • Системный программист: подумайте о переполнении и атомарности в многопоточности.

Короткий глоссарий

  • Алиасинг — ситуация, когда две переменные ссылаются на один и тот же объект или адрес.
  • Переполнение — выход арифметического результата за пределы представимого диапазона типа.
  • Атомарность — операция, завершающаяся целиком без вмешательства других потоков.

Мерmaid: как выбрать метод

flowchart TD
    A[Нужно поменять два числа?] --> B{Язык поддерживает распаковку/ swap}
    B -- Да --> C[Использовать встроенный swap/распаковку]
    B -- Нет --> D{Тип целый и критична память}
    D -- Да --> E[Рассмотреть XOR]
    D -- Нет --> F[Использовать временную переменную]
    E --> G{Алиасинг?}
    G -- Да --> F
    G -- Нет --> H[Использовать XOR]

Примеры улучшений и альтернатив

  • В C++ для реального обмена переменных, доступных по ссылке, стоит реализовать функцию void swap(int &a, int &b) с использованием temp или std::swap.
  • Для обмена элементов контейнера используйте std::iter_swap для безопасности и читаемости.

Дополнительно: улучшение практик программирования

Следуйте принципам KISS и DRY: не усложняйте код ради микрооптимизаций. Если встречаются частые операции обмена — используйте читаемые утилиты или стандартные функции. Проверяйте крайние случаи в тестах.

Если хотите посмотреть полный исходный код, можно хранить примеры в репозитории GitHub и ссылаться на него в проекте.

Краткое резюме

  • Для большинства задач используйте временную переменную или встроенные механизмы языка.
  • Арифметические или битовые трюки полезны как учебные примеры, но уязвимы к границам и условиям исполнения.
  • Тестируйте граничные случаи и думайте о многопоточности.

Notes: при выборе метода руководствуйтесь безопасностью и простотой поддержки, а не только экономией одной переменной.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Несколько аккаунтов Skype: Multi Skype Launcher
Программное обеспечение

Несколько аккаунтов Skype: Multi Skype Launcher

Журнал для работы: повысить продуктивность
Productivity

Журнал для работы: повысить продуктивность

Персональные звуки уведомлений на Android
Android.

Персональные звуки уведомлений на Android

Скачивание шоу Hulu для офлайн‑просмотра
Стриминг

Скачивание шоу Hulu для офлайн‑просмотра

Microsoft Start: персонализированная новостная лента
Новости

Microsoft Start: персонализированная новостная лента

Как изменить имя в Epic Games быстро
Гайды

Как изменить имя в Epic Games быстро