Другое

Почему унарный плюс в PHP не меняет знак числа

Узнаем, почему унарный оператор + в PHP преобразует тип, но не меняет знак числа, а унарный - выполняет и преобразование, и инвертирование знака.

Почему в PHP унарная операция от плюса к минусу работает, а обратно нет? Меня сложно чем‑то удивить, но это поведение меня озадачило. В PHP 8.3 при выполнении кода:

$a = 100;
= 100

b=b = -a;
= -100

c=+c = +b;
= -100

Унарный плюс не изменяет знак отрицательного числа. В PHP же нет унарных операций? А тут будто бы она есть, но только в одну сторону… Как это работает и почему?

В PHP унарная операция + на самом деле не предназначена для изменения знака числа, а скорее для явного преобразования значения в числовой тип. Унарный оператор - как раз выполняет изменение знака. Такое поведение является частью спецификации языка и связано с тем, как PHP обрабатывает числовые преобразования.

Содержание

Базовое объяснение поведения унарных операторов

Унарный оператор + в PHP выполняет только преобразование значения в числовой тип, но не изменяет его знак. Унарный оператор - выполняет две операции: преобразование в числовой тип и инвертирование знака.

php
$a = 100;        // = 100 (целое число)
$b = -$a;        // = -100 (преобразование в число + инвертирование знака)
$c = +$b;        // = -100 (только преобразование в число, знак остается)

Это объясняется тем, что согласно документации PHP, унарный плюс предназначен для явного приведения к числовому типу, а унарный минус - для отрицания значения.


Технические детали реализации

Как PHP обрабатывает унарные операторы

Согласно исследованиям, унарный оператор + эквивалентен вызову Number() конструктора как функции, в то время как унарный оператор - сначала преобразует операнд в число, а затем инвертирует его знак.

php
// Внутренняя обработка PHP
+$b;    // эквивалентно Number($b) - просто преобразование типа
-$b;    // эквивалентно -(Number($b)) - преобразование + инвертирование

Типы данных и преобразования

При использовании унарных операторов PHP выполняет автоматическое приведение типов:

php
$str = "123";
$num = 456;

+$str;   // = 123 (строка преобразуется в число)
-$str;   // = -123 (строка преобразуется в число и инвертируется)
+$num;   // = 456 (число остается без изменений)
-$num;   // = -456 (число инвертируется)

Сравнение с другими языками программирования

Сходства и различия

Язык Унарный + Унарный - Примечания
PHP Только преобразование типа Преобразование + инвертирование Встроенное поведение
JavaScript Только преобразование типа Преобразование + инвертирование Похожее поведение
Python Преобразование в число Преобразование + инвертирование Аналогично
C/C++ Преобразование в int Преобразование + инвертирование Работает с целыми числами
Java Преобразование в int Преобразование + инвертирование Аналогично C/C++

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


Практические примеры использования

Преобразование строк в числа

Унарный + часто используется для быстрого преобразования строк в числа:

php
$numericString = "42";
$number = +$numericString;  // = 42

// Эквивалентно:
$number = (int)$numericString;  // или (float) для дробных чисел

Динамические математические операции

Унарные операторы полезны в динамических вычислениях, как показано в примере из StackOverflow:

php
$variable = 1;
$modifier = ($variable == 1) ? -1 : 1;

$numberOne = 10;
$numberTwo = 10;
$result = $numberOne + ($numberTwo * $modifier);

Работа с отрицательными нулями

Интересный случай описан в баг-репорте PHP:

php
$negativeZero = -0.0;
$positiveZero = +$negativeZero;  // produces positive zero

Почему так было сделано?

Дизайн-решения PHP

Такое поведение унарных операторов было сделано по нескольким причинам:

  1. Ясность намерений: Унарный + явно указывает на необходимость преобразования в число, а не на изменение знака.
  2. Соответствие стандартам: Такое поведение соответствует стандартам ECMAScript и другим языкам программирования.
  3. Предсказуемость: Разделение операций преобразования типа и математического инвертирования делает код более предсказуемым.
  4. Производительность: Отдельные операции позволяют PHP выполнять оптимизацию преобразований типов.

Исторический контекст

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


Как получить положительное число из отрицательного

Если вам нужно превратить отрицательное число в положительное, используйте следующие подходы:

Использование математических функций

php
$negativeNumber = -100;
$positiveNumber = abs($negativeNumber);  // = 100

Умножение на -1

php
$negativeNumber = -100;
$positiveNumber = -$negativeNumber;  // = 100 (двойное инвертирование)

Условный оператор

php
$number = -100;
$positive = $number < 0 ? -$number : $number;  // = 100

Bitwise операции (для целых чисел)

php
$negativeNumber = -100;
$positiveNumber = $negativeNumber & 0xFFFFFFFF;  // для 32-битных чисел

Заключение

  1. Унарный + в PHP предназначен только для преобразования значения в числовой тип, а не для изменения знака.
  2. Унарный - выполняет две операции: преобразование в число и инвертирование знака, что делает его “двусторонним” оператором изменения знака.
  3. Такое поведение вполне осознанное и документированное, а не ошибка или особенность реализации.
  4. Для получения положительного числа из отрицательного следует использовать abs(), умножение на -1 или другие математические операции.
  5. Такое разделение операций сделано преднамеренно для ясности кода и соответствия стандартам программирования.

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

Источники

  1. PHP: Operators - Manual
  2. Unary Operators in PHP - Tutorial
  3. What’s the significant use of unary plus and minus operators? - StackOverflow
  4. Store plus and minus in a variable PHP - StackOverflow
  5. PHP :: Bug #70804 :: Unary add on negative zero produces positive zero
  6. Unary operation - Wikipedia
  7. 17.2: Unary Positive and Negative Operators - Engineering LibreTexts
Авторы
Проверено модерацией
Модерация