Сюрпризы унарного минуса
Другие статьи из серии «Конспекты начинающего программиста»:
- Как я поборол рекурсию: учебный детектив;
- Опциональные типы данных в языке Swift;
- Кортежи (tuples) в Swift;
- Моделирование объектов в Swift.
Небольшая предыстория
При изучении темы «Операторы» унарные операторы обычно рассматриваются в начале или где-то бегло по ходу, поскольку они вроде простые и излагать там особо нечего. В данном же случае обнаружились некоторые сюрпризы, о которых не говорится в учебнике по Swift. Поэтому представляется удобным выделить их в отдельный текст.
Всё началось с того, что захотелось вживую в XCode прописать примеры из учебника. И вот что из этого вышло.
Что такое унарный минус?
Для начала напомним, что такое унарный минус, а точнее — что о нём говорится в учебнике. Унарный минус — это унарный оператор, который служит для изменения знака числового значения.
Пример 1: Каждый раз новые константы
И далее в учебнике даётся следующий пример, который цитируется во многих других текстах:
let three = 3
let minusThree = -three // minusThree равно -3
let plusThree = -minusThree // plusThree равно 3, т. е. «минус минус три»
Всё красиво и вроде понятно. Берём константу с числовым положительным значением, присваиваем ей унарный минус, получается отрицательное число. Далее, добавляем ещё один унарный минус и получаем снова плюс, т.е. по известному из арифметики правилу — минус на минус, получаем плюс.
Но есть одна особенность в этом примере, а именно — на каждом шаге объявляется новая константа! Вроде бы ничего такого, но, наверное, авторы учебника что-то знали! И решили пока не загружать умы учеников сложной информацией. Но ученики тоже, бывает, замечают, что что-то не вписывается в гладкую последовательность изложения.
Пример 2: Меняем знак на одной и той же переменной
После прочтения учебника складывается впечатление, что ничего особенного здесь нет и все как в арифметике (см. выше). Но если мы попробуем проделать ту же операцию без создания каждый раз новой константы, то столкнемся с неведомым. Начнём следующий пример:
- var a = 1 // Переменная а равна 1
- -a // Переменная а равна -1
Пока всё идёт в штатном режиме. Но если попробуем пойти дальше и ещё раз сменим знак, то получим сюрприз:
- var a = 1 // Переменная а равна 1
- -a // Переменная а равна -1
- -a // Переменная а равна -1
Т.е. второго изменения знака — с минуса на плюс — не происходит! Правило «минус на минус даёт плюс» в данном случае не срабатывает!
Почему это происходит?
Гипотез было несколько. Первая уже названа: что в первом примере на каждое применение унарного минуса создавалась новая константа, а во втором примере унарный минус использовался на одной и той же переменной. Но что потом делать с этой гипотезой не понятно, потому что она просто закрывает все дальнейшие вопросы, ничего не объясняя.
Вторая гипотеза: унарный минус действует только один раз, а второе его применение использует значение не из предыдущей строки, а из строки, где переменная объявляется. Кстати, если продолжать ставить минусы, то значение не меняется, везде будет минус 1. Это тоже такая гипотеза методом «научного тыка»: а вдруг что-то произойдет, если ставить минусы дальше? Не происходит!
Следующее экспериментальное действие: а если просто указать переменную без минуса, что тогда будет? По идее в песочнице должно появиться значение переменной на данный момент. Т.е. мы его меняли, меняли, а теперь хотим посмотреть, какое текущее значение у этой переменной. Смотрим:
- var a = 1 // Переменная а равна 1
- -a // Переменная а равна -1
- -a // Переменная а равна -1
- -a // Переменная а равна -1
- a // Переменная а равна 1
И снова сюрприз: мы-то ожидали, что значение переменной изменилось во 2-й строке (а потом и в 3-й, и в 4-й), что оно теперь минус один, а на самом деле оно просто один, без минуса! И опять непонятно почему это происходит?
То ли минус действует только на одну операцию, там где применяется, то ли повторное указание переменной без минуса автоматом переводит число из отрицательного в положительное, по типу плюс по умолчанию, который даже не показывается.
Следующее предположение: а что если нужно поставить второй минус? Может один минус это просто повторение операции смены положительного числа на отрицательное, а чтобы сменить отрицательное на положительное надо ещё один минус? По ходу вспоминается, что где-то упоминались двойные операторы, типа два плюса или два минуса, но сейчас пока не до них, просто пробуем:
- var a = 1 // Переменная а равна 1
- -a // Переменная а равна -1
- -a // Переменная а равна -1
- -a // Переменная а равна -1
- a // Переменная а равна 1
- //—a // XCode выдает ошибку ‘—‘ is unavailable: it has been removed in Swift 3
Ничего не получилось. Но хотя бы по ходу узнаём, что двойные минусы совсем удалены в третьем Swift. Т.е. получаем облом, который толкает на следующую авантюру: а что если взять переменную с первым минусом в скобки, типа соорудить конструкцию похожую на логическую — «минус на минус…». Делаем (см. строку 7):
- var a = 1 // Переменная а равна 1
- -a // Переменная а равна -1
- -a // Переменная а равна -1
- -a // Переменная а равна -1
- a // Переменная а равна 1
- //—a // XCode выдает ошибку ‘—‘ is unavailable: it has been removed in Swift 3
- -(-a) // Переменная а равна 1
Бинго!
Мы своего добились! Применили два минуса и на выходе получили плюс! На всякий случай для страховки проверяем, т.е. указываем просто переменную a:
- var a = 1 // Переменная а равна 1
- -a // Переменная а равна -1
- -a // Переменная а равна -1
- -a // Переменная а равна -1
- a // Переменная а равна 1
- //—a // XCode выдает ошибку ‘—‘ is unavailable: it has been removed in Swift 3
- -(-a) // Переменная а равна 1
- a // Переменная а равна 1
Отлично! Всё сохраняется, значение нашей переменной снова положительное. Вопросы конечно оставались: почему унарный минус так себя ведёт? Единственное объяснение: он почему-то действует только тогда, когда применяется, но само изменённое значение дальше не сохраняется.
Пример 3. Гештальт
И вот, как это часто бывает, долгие раздумья над каким-то вопросом вдруг приводят к новому повороту. Как говорится, гештальт созрел. Сначала была мысль, что один и тот же знак, минус, используется и как унарный оператор, и как бинарный арифметический. Разница только в синтаксисе: бинарному нужны 2 операнда и он пишется с пробелами, унарному нужен только один операнд и он пишется без пробела от операнда.
Затем настойчивые мысли о том, почему значение не сохраняется, вывели на оператор присвоения. Т.е. унарный минус значение меняет, но оно не сохраняется, т.е. оно НЕ ПРИСВАИВАЕТСЯ переменной! Отсюда логично напрашивается использовать оператор присвоения.
Тут же вспоминаются бинарные составные операторы, где используются знаки минуса и плюса и знак присвоения (=). Но это не совсем то, потому как здесь минус и плюс используются именно как бинарные арифметические операторы. Но направление мысли они задают, как оказалось, правильное. А именно — попробовать не только изменить знак числа, но и присвоить это изменённое значение переменной.
Делаем простой развёрнутый пример со сменой знака и сразу же проверяем текущее значение переменной (9-я и 10-я строки):
- var a = 1 // Переменная а равна 1
- -a // Переменная а равна -1
- -a // Переменная а равна -1
- -a // Переменная а равна -1
- a // Переменная а равна 1
- //—a // XCode выдает ошибку ‘—‘ is unavailable: it has been removed in Swift 3
- -(-a) // Переменная а равна 1
- a // Переменная а равна 1
- a = -a // Переменная а равна минус 1
- a // Переменная а равна минус 1
Ура ещё раз!
Значение переменной изменилось в 9-й строке, а в 10-й видно, что оно сохранилось! Т.е. впервые, когда мы просто указываем название переменной, её значение в строке 10 отличается от значения в первой строке!
Ещё раз подчеркнём: раньше по ходу примера, когда просто указывалось название переменной, то её значение всегда было таким, как и в первой строке, т.е. единица. А в 10-й строке мы впервые получаем при той же записи другое значение — единицу в минусе.
Таким образом, приходим к выводу, что эта последняя гипотеза правильная. А именно — унарный минус только меняет значение с плюса на минус, но он это новое значение автоматически не сохраняет, не присваивает переменной. Чтобы сохранить новое значение надо специально использовать оператор присвоения.
И кстати, с этой точки зрения можно заметить, что в 8-й строке мы не можем утверждать, что новое значение переменной сохранилось, как мы радовались этому немного ранее. Скорее всего в этой строке показывалось не изменённое с плюса на минус и потом с минуса на плюс значение переменной, а всё то же значение из первой строки. Т.е. все предыдущие изменения знака в переменной не сохранялись, потому что не использовался оператор присвоения. И только когда мы используем оператор присвоения, только тогда изменённое значение сохраняется и число в переменной остаётся с другим знаком.
Резюме по унарному минусу
В ходе своего учебного расследования 🙂 мы выяснили как минимум 3 вещи:
- Если мы захотим изменить знак числа в переменной с плюса на минус с помощью унарного минуса, а потом ещё раз изменить с минуса на плюс с помощью того же унарного минуса, то у нас это не получится.
- Если же все-таки надо это сделать, т.е. вторым минусом изменить минус на плюс, тогда следует использовать конструкцию со скобками:
Не берусь судить, бывают ли такие ситуации, когда такое нужно сделать, но в программировании всякое возможно. Так что пусть будет, может когда и пригодится.
- Унарный минус меняет знак числа в переменной, но новое измененное значение не сохраняется. Оно существует только в момент применения унарного минуса. А дальше по ходу программы будет использоваться исходное значение переменной до применения унарного минуса.
Если же нам нужно сохранить измененное значение, тогда следует использовать ещё и оператор присвоения. Т.е. изменить знак числа и присвоить это измененное число переменной.
Это можно сделать либо способом, где изменённое значение присваивается той же переменной:
либо так, как показано в учебнике, т.е. присваивая изменённые значения новым переменным / константам:
let three = 3
let minusThree = -three // minusThree равно -3
let plusThree = -minusThree // plusThree равно 3, т. е. «минус минус три»
Пару слов об унарном плюсе
Об унарном плюсе говорить действительно почти нечего. Он просто возвращает исходное значение без изменений. Например:
var b = -20 // Переменная b равна минус 20
+b // Переменная b равна минус 20
var c = 30 // Переменная c равна 30
+c // Переменная c равна 30
Как сказано в учебнике: хотя оператор унарного плюса не выполняет никаких действий, он придаёт коду единообразие, позволяя зрительно отличать положительные значения от отрицательных. Но что-то мне сдаётся по типу нововведений в Swift 3, что потом с этим унарным плюсом может что-то и произойти для единообразия.
Унарный логический оператор
Унарный логический оператор в учебнике рассматривается в разделе «Логические операторы». С одной стороны это логично, с другой — не очень, поскольку вначале задана классификация на унарные, бинарные и тернарный операторы, а потом она нарушается. Поэтому здесь пробуем расположить унарный логический оператор в разделе именно «Унарные операторы» в соответствии с заданной в начале главы классификацией.
Итак, есть один унарный логический оператор. Его полное название — оператор логического НЕ. Обозначается этот оператор восклицательным знаком — !.
Его действие: он изменяет, инвертирует значение логической переменной с true на false или с false на true.
Синтаксис: унарный логической оператор также как и унарный минус ставится перед названием переменной без пробела.
- var k = true // Переменная k есть true
- !k // Переменная k есть false
В учебнике предлагается описывать действие унарного оператора логического НЕ как «не есть такая-то переменная». Отсюда, в нашем примере смысл второй строки можно описать так: «!k не есть переменная k». Или так — «значение !k не есть истинное значение переменной k, оно фальшивое, ненастоящее».
И далее, также как в случае с унарным минусом, новое значение логической переменной не сохраняется и действует только в момент использования унарного логического оператора. Т.е. если мы попытаемся ещё раз изменить значение переменной с false на true, то у нас ничего не получится.
- var k = true // Переменная k есть true
- !k // Переменная k есть false
- !k // Переменная k есть false
Чтобы поменять значение переменной второй раз, т.е. от false перейти к true, нужно использовать круглые скобки:
- var k = true // Переменная k есть true
- !k // Переменная k есть false
- !k // Переменная k есть false
- !(!k) // Переменная k есть true
А если мы хотим не только изменить значение логической переменной на противоположное, но ещё и сохранить его, то нам нужно изменённое значение присвоить или той же переменной, или новой (см. строки с 5-ой по 8-ю):
- var k = true // Переменная k есть true
- !k // Переменная k есть false
- !k // Переменная k есть false
- !(!k) // Переменная k есть true
- k = !k // Переменная k есть false, измененное значение сохранено
- k // Проверка. Результат — переменная k есть false
- var l = !k // Переменная k есть true и это значение присвоено новой переменной l
- l // Проверка. Результат — переменная l есть true
Ещё одно интересное наблюдение: унарный логический оператор также можно использовать не только по отношению к переменной, но и по отношению к голому значению. Т.е. также, как мы можем к 2 добавить минус и получить -2, так и к булевым значениям мы можем применять логический унарный оператор и изменять его на противоположное. Например:
true // Песочника показывает true
!true // Песочница показывает false
И последнее по унарному логическому оператору: он используется только в префиксном варианте, т.е. ставится только перед названием переменной или перед булевым значением.
Помнится раньше в Swift были и постфиксные операторы, но сейчас, начиная с версии 3, их уже похоже нет. И хотя в информации об обновлениях об этом прямо не сказано, но если попытаться поставить ! после переменной, то выдаёт ошибку, что не может сделать force unwrap, поскольку переменная с логическом типом данных не содержит опционального значения. Т.е. скорее всего, постфиксный восклицательный знак отдан под опционалы.
В принципе всё логично, постфиксные операторы как-то выбивались из общего строя. Теперь без них будет проще: есть префиксные и всё понятно и единообразно. А вы как считаете?
Что такое унарный минус
Унарный минус (-. )
Навигация
Язык:
Русский
English
Унарный минус возвращает отрицательное значение выражения, стоящего после знака минус.
Выражение должно быть абсолютным непосредственным значением.
Код для вставки: :: :: :: ГОСТ ::
Поделиться: //
Для форумов:
Для блогов:
Для Википедии:
Что такое унарный минус
Argument ‘Topic id’ is null or empty
Сейчас на форуме
© Николай Павлов, Planetaexcel, 2006-2023
info@planetaexcel.ru
Использование любых материалов сайта допускается строго с указанием прямой ссылки на источник, упоминанием названия сайта, имени автора и неизменности исходного текста и иллюстраций.
ООО «Планета Эксел» ИНН 7735603520 ОГРН 1147746834949 | ИП Павлов Николай Владимирович ИНН 633015842586 ОГРНИП 310633031600071 |
Унарный минус
Входной сигнал, заданный как скаляр, вектор, матрица или массив N-D.
Типы данных: single | double | int8 | int16 | int32 | fixed point
Вывод
Port_1 — Отрицание входного сигнала
скаляр | вектор | матрица | массив N-D
Отрицание входного сигнала. Вывод имеет совпадающий тип данных и размерности как вход.
Типы данных: single | double | int8 | int16 | int32 | fixed point
Параметры
Saturate on integer overflow — Метод действия переполнения
off (значение по умолчанию) | on
Выбор, чтобы иметь целочисленное переполнение насыщает. В противном случае переполнение переносится.
Когда вы устанавливаете этот флажок, насыщение применяется к каждой внутренней операции на блоке, не только выводу или результату. В целом процесс генерации кода может обнаружить, когда переполнение не возможно. В этом случае генератор кода не производит код насыщения.
Для типов данных целого числа со знаком унарное минус наиболее отрицательной величины не является представимым, по условию вводят. В этом случае флажок Saturate on integer overflow управляет поведением блока:
- Для 8-битных целых чисел со знаком,-128 карт к 127.
- Для 16-битных целых чисел со знаком,-32768 карт к 32 767.
- Для 32-битных целых чисел со знаком,-2147483648 карт к 2147483647.
- Для 8-битных целых чисел со знаком,-128 остается-128.
- Для 16-битных целых чисел со знаком,-32768 остается-32768.
- Для 32-битных целых чисел со знаком,-2147483648 остается-2147483648.
Программируемое использование
Параметры блоков: SaturateOnIntegerOverflow |
Ввод: символьный вектор |
Значения: ‘off’ | ‘on’ |
Значение по умолчанию: ‘off’ |
‘SampleTime’ Задайте шаг расчета как значение кроме -1
-1 (значение по умолчанию) | скаляр
Задайте шаг расчета как значение кроме-1. Для получения дополнительной информации см. Настройку времени выборки.
Зависимости
Этот параметр не видим, если он явным образом не установлен в значение кроме -1 . Чтобы узнать больше, смотрите Блоки, для Которых Не Рекомендуется Шаг расчета.
Программируемое использование
Параметры блоков: SampleTime |
Ввод: символьный вектор |
Значения: скаляр |
Значение по умолчанию: ‘-1’ |
Образцовые примеры
Унарный минус матричного входа
Вычислите унарное минус матричного входа.
Характеристики блока
Типы данных
double | fixed point[a] | integer[a] | single
Прямое сквозное соединение
Многомерные сигналы
Сигналы переменного размера
Обнаружение пересечения нулем
[a] Этот блок только поддерживает подписанные типы данных с фиксированной точкой.
Расширенные возможности
Генерация кода C/C++
Генерация кода C и C++ с помощью Simulink® Coder™.
Генерация HDL-кода
Сгенерируйте Verilog и код VHDL для FPGA и проекты ASIC с помощью HDL Coder™.
Для получения дополнительной информации о генерации HDL-кода, смотрите Унарный Минус .
Генерация кода PLC
Сгенерируйте код Структурированного текста с помощью Simulink® PLC Coder™.
Преобразование фиксированной точки
Преобразуйте алгоритмы с плавающей точкой в фиксированную точку с помощью Fixed-Point Designer™.
Этот блок только поддерживает подписанные типы данных с фиксированной точкой.
Смотрите также
Темы
- Приоритет операторов (MATLAB)
Представлено до R2006a
Документация Simulink
- Примеры
- Блоки и другая ссылка
- Информация о релизах
- PDF-документация
Поддержка
- MATLAB Answers
- Помощь в установке
- Отчеты об ошибках
- Требования к продукту
- Загрузка программного обеспечения
© 1994-2019 The MathWorks, Inc.
- Условия использования
- Патенты
- Торговые марки
- Список благодарностей
Для просмотра документации необходимо авторизоваться на сайте
Войти
Памятка переводчика
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста — например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.