Перейти к содержимому

С помощью чего меняется порядок вычислений

  • автор:

Порядок выполнения действий в формулах Excel

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

  • Порядок вычислений Формулы вычисляют значения в определенном порядке. Формула в Excel всегда начинается со знака равно (=). Excel интерпретирует символы после знака равно как формулу. После знака равно вычисляются элементы (операнды), например константы или ссылки на ячейки. Они разделены операторами вычислений. Excel вычисляет формулу слева направо в соответствии с определенным порядком для каждого оператора в формуле.
  • Приоритет операторов в формулах Excel Если в одной формуле используется несколько операторов, Microsoft Excel выполняет операции в порядке, указанном в приведенной ниже таблице. Если формула содержит операторы с одинаковым приоритетом ( например, если формула содержит операторы умножения и деления), Excel оценивает операторы слева направо.

Оператор Описание
: (двоеточие) (один пробел) , (запятая) Операторы ссылок
Знак «минус»
% Процент
^ Возведение в степень
* и / Умножение и деление
+ и — Сложение и вычитание
& Объединение двух текстовых строк в одну
=
< >
>=
<>
Операторы сравнения

2.6. От перемены мест слагаемых сумма не изменяется

Еще недавно, учась сложению чисел, мы складывали кучки из монет. Тогда перед нами стояла задачи сложить две кучки. Но допустим, мы хотим теперь сложить не две, а несколько кучек. Это можно было бы сделать так: сгребаем их все сразу в одну большую кучу и пересчитываем в ней все монеты. Такой способ сложения всем бы был хорош, да только ни на счетах, ни на бумаге нельзя сделать ничего подобного. На счетах и бумаге мы умеем складывать между собой только два числа. Поэтому мы не будем сгребать вместе сразу все кучки, а поступим так, чтобы все наши действия можно было легко перенести на бумагу.

Итак, перед нами несколько кучек из монет. Мы знаем, сколько монет в каждой кучке, и теперь мы хотим узнать, сколько же у нас всего монет во всех кучках. Мы берем любые две кучки и сдвигаем их вместе, образуя одну новую кучку побольше. Умея складывать два числа на бумаге, мы сможем легко вычислить, сколько у нас монет в новой кучке без фактического их пересчета. Теперь у нас стало на одну кучку меньше. Далее, берем еще две кучки, сливаем их воедино, вычисляем новое число монет в только что образованной кучке и, таким образом, снова уменьшаем количество кучек на одну. Мы повторяем и повторяем эту процедуру, уменьшая всякий раз число кучек на единицу, до тех пор пока у нас не останется одна-единственная большая куча. Число монет в этой куче нам известно, причем вычислили мы его на бумаге, а не прямым пересчетом.

Очевидно, мы получим один и тот же ответ, совершенно независимо от того, в каком порядке мы сдвигали кучки. А значит, когда перед нами находится сумма чисел, например,

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

$8 + 2 + 9 = 10 + 9 = 19$.

Но математический язык — это язык строгих правил. Спрашивается: на основании какого правила мы можем произвольно менять порядок вычислений при нахождении суммы нескольких слагаемым? Мы знаем, например, свойство коммутативности (которое, на школьном языке, называется также переместительным свойством сложения):

Можем ли мы, опираясь на это свойство, написать

$8 + 9 + 2 = 8 + 2 + 9$,

то есть просто переставить местами девятку и двойку, подобно тому, как мы меняем местами переменные $a$ и $b$? Оказывается, нет, не можем. Вспомним, что, собственно, означает запись

Это, как мы раньше договорились, всего лишь упрощенный вариант более подробной записи

Коммутативность сложения означает, что мы можем переставлять местами два непосредственно складываемых друг с другом числа. То есть, мы можем написать так:

$(8 + 9) + 2 = (9 + 8) + 2$,

$(8 + 9) + 2 = 2 + (8 + 9)$,

$(8 + 9) + 2 = 2 + (8 + 9) = 2 + (9 + 8)$,

однако при этом никак нельзя сделать так, чтобы восьмерка вначале складывалась с двойкой, а потом прибавлялась девятка. Коммутативность означает, что мы можем с одинаковым результатом либо кучку $a$ придвинуть к кучке $b$, либо наоборот, кучку $b$ придвинуть к кучке $a$, но коммутативность не позволяет произвольно выбирать пары кучек для слияния.

Как же быть? Мы должны вспомнить еще об одном свойстве сложения, а именно об ассоциативности (на школьном языке оно называется сочетательным свойством сложения):

$(a + b) + c = a + (b + c)$.

Это свойство действительно позволяет менять порядок объединения кучек. Впрочем, далеко не произвольно. Мы теперь можем написать так:

$(8 + 9) + 2 = 8 + (9 + 2)$.

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

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

$(8 + 9) + 2 = 8 + (9 + 2)$.

Теперь воспользуемся коммутативностью и поменяем местами девятку и двойку:

$8 + (9 + 2) = 8 + (2 + 9)$.

Далее, снова воспользуемся ассоциативностью:

$8 + (2 + 9) = (8 + 2) + 9$.

И наконец, перепишем конечное выражение в упрощенном виде:

$(8 + 2) + 9 = 8 + 2 + 9$.

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

нам тоже надо будет действовать по правилам? Разве мы не сможем сразу переписать его в удобном виде:

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

Начнем с того, что так уж устроена математика: ученые-математики вначале вводят хорошо продуманные правила, а потом неукоснительно им следуют. Другое дело, что нам с вами (пока еще не ученым), для того чтобы хорошо решать школьные задачи, достаточно знать эти правила в сильно упрощенной форме. Я бы и не рассказывал вам ничего про коммутативность и ассоциативность, да только в школьных учебниках эти свойства (правда, под другим названием) выписаны жирным шрифтом и обведены в рамочку. При этом, однако, толком не объясняется, зачем они нужны и как их применять. Поэтому они моментально улетучиваются из памяти, что, в свою очередь, приводит к неприятностям на устных опросах и контрольных работах.

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

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

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

Теперь нам осталось уточнить еще один важный момент. Мы знаем, что складывать можно не только натуральные числа, но и целые, которые бывают и отрицательными. Спрашивается: если в сумме присутствуют отрицательные числа, то можно ли и в этом случае произвольно менять порядок суммирования?

Рассуждения с кучками монет нам теперь не помогут, потому что очень трудно представить себе кучку с отрицательным количеством монет. Но мы пойдем на этот раз другим путем. У нас уже есть некоторый опыт обращения с целыми числами, и мы имели возможность убедиться, что свойства коммутативности и ассоциативности для них сохраняются. Разумеется, наш опыт очень ограничен: ведь мы же не перебирали всех возможных комбинаций с целыми числами. Так что сомнения на этот счет вполне оправданы, и тот, у кого они возникли, может поискать опровержение. Только я не советую тратить на это слишком уж много времени, поскольку найти такое опровержение пока еще никому не удавалось. Поэтому давайте отнесемся как к факту, что сложение коммутативно и ассоциативно для любых целых чисел; и тогда из нашего общего утверждения (принятого на веру) со всей определенностью будет следовать, что порядок суммирования никак не влияет на значение суммы, даже если среди слагаемых есть отрицательные числа. Напомню, кстати, что любую разность можно переписать в виде суммы, например:

$5 — 3 = 5 + (-3)$,
$5 — (4 — 1) = 5 + (-4) + 1$.

Конспект

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

2.6.1. Вычислить наиболее удобным способом:

2.6.2. Вычислить наиболее удобным способом:

Порядок вычислений выражений

Есть такая штука, как [порядок выполнения операторов]. Он никогда не меняется и, если в нем разобраться, пару раз поможет распутать баги.

8 апр 2014 в 8:41

Сомнения основаны на теме связанной с С++ на msdn social.msdn.microsoft.com/Forums/ru-RU/… «Т.е. никто и никогда не даст вам 100% гарантию того, что первым будет вычислен первый аргумент – i++, а вторым – i + 2. Т.е. результат может быть как: -2, так и 1. Это относится к C# в том числе.» Или это касается исключительно аргументов функций?

8 апр 2014 в 11:52
мы изначально говорили о немного разных вещах. Поправил ответ
8 апр 2014 в 12:41
8 апр 2014 в 15:16

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Порядок вычисления аргументов методов определен в пункте 7.5.1.2 стандарта:

7.5.1.2 Run-time evaluation of argument lists During the run-time processing of a function member invocation (§7.5.4), the expressions or variable references of an argument list are evaluated in order, from left to right

То есть параметры вычисляются слева направо. Получается, что либо ошибается стандарт, либо тот человек, с форума msdn, на чьи слова вы ссылались.

Однако существует такое понятие, как побочные эффекты функций. Так вот помимо вышесказанного необходимо, чтобы функции (а с ними и их побочные эффекты) выполнялись в той очередности, в которой объявлены, а параметры передавались слева направо в соответствии с сигнатурой. Например:

public static void Write(int i, int b) < Console.WriteLine("", i, b); > public static int First(ref int i) < Console.WriteLine("first"); return ++i; >public static int Second(ref int i) < Console.WriteLine("second"); i += 2; return i; >int i = 5; i = 5; /* тут все логично, выведет строки first second 6 8 потому что сначала First вернет ++i (то есть 6) а затем Second вернет i + 2 (то есть 8) */ Write(First(ref i), Second(ref i)); i = 5; /* а вот тут выведет first second 8 6 и результат может быть неожиданным, потому что компилятор сначала выполняет первую функцию, занося ее результат во второй параметр, а затем вторую, занося ее результат в первый параметр */ Write(b: First(ref i), i: Second(ref i)); 

Что касается операторов: у каждого оператора в C# (как и в других языках) есть свой приоритет и ассоциативность (он же порядок выполнения). Кроме того, C# в отличие от С++ лишен всяческих источников головной боли, связанных с UB, а потому всегда можно предсказать порядок выполнения и резуьтат выражения (хотя для человека это подчас нетривиальная и запутанная задача). Большая часть операторов в C# левоассоциативны (то есть выполняются слева направо). Однако не все (например, оператор присваивания выполняется справа налево). Подробнее о приоритете и ассоциативности можно почитать тут

Напоследок стоит заметить, что усложнять себе жизнь таким кодом, как вы привели выше, не стоит — компилятор способен разобрать это без труда, а вот человеку гораздо сложнее. Думаю, выпадать в осадок после часовой отладки багов, связанных с неверно рассчитанным приоритетом операций и побочными действиями функций (а в вашем коде есть и такое, что в общем-то тоже не приветствуется) — это далеко не предел мечтаний в работе программиста. Поэтому в подобных ситуациях лучше не жалеть скобочек для группировки операций — компилятор сожрёт, а человеку читать будет легче. Ну или даже разбивать операции на отдельные выражения

Приоритеты операторов Python

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

Оператор возведения в степень исключение из этого правила. Из двух операторов ** сначала выполнится правый, а потом левый.

Операторы Описание
() Скобки
** Возведение в степень
+x , -x , ~x Унарные плюс, минус и битовое отрицание
* , / , // , % Умножение, деление, целочисленное деление, остаток от деления
+ , — Сложение и вычитание
> Битовые сдвиги
& Битовое И
^ Битовое исключающее ИЛИ ( XOR )
| Битовое ИЛИ
== , != , > , >= , < , Сравнение, проверка идентичности, проверка вхождения
not Логическое НЕ
and Логическое И
or Логическое ИЛИ

Python с нуля. Освойте с Виртуальным ИИ-помощником!

Теоретические уроки и практические задачи
Пишите и проверяйте код прямо в браузере
Виртуальный ИИ-помощник поможет в любое время дня и ночи
Сообщество учеников для взаимопомощи и обмена опытом
200 000+ зарегистрированных участников. Присоединяйтесь!
Попробовать бесплатно
©2023 Letpy

Мы используем файлы cookie

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *