Изучаем операторы в PHP: теория и практика

На уроке рассмотрен синтаксис и примеры использования условные операторов php: оператора if, оператора переключения switch и тернарного оператора

Null-коалесцентный оператор

Решает распространенную проблему в PHP.
Она возникает в случае, если мы хотим присвоить значение переменной, которое присвоено другой переменной, но если последней переменной значение не было присвоено (isset), то присвоить некое явное значение по умолчанию.

Часто проявляется при работе с пользовательским вводом.

До PHP 7:

if (isset($foo)) { $bar = $foo;} else { // присваиваем $bar значение ‘default’ если $foo равен NULL $bar = ‘default’; }

В PHP 7 (теперь можно)):

$bar = $foo ?? ‘default’;

Можно использовать с цепочкой переменных:

$bar = $foo ?? $baz ?? ‘default’;

Источник: http://php.net/manual/ru/migration70.new…

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

Начнём с того, что операторы имеют разный приоритет. Как, например, в математике: оператор умножения будет более приоритетным по сравнению с оператором сложения:

<?php$result = 2 + 2 * 2;var_dump($result);

Результат:

int 6

Приоритетом можно управлять с помощью круглых скобок, например:

<?php$result = (2 + 2) * 2;var_dump($result);

Ну и тут думаю всё понятно:

int 8

В целом приоритеты операторов довольно предсказуемы.
Приоритет всех операторов в PHP можно посмотреть в официальной документации.

Как переводятся названия частей

Всё предельно просто:

  • if – если. Всегда стоит перед остальными условиями. На одной строчке с ним в скобках должно находиться сравниваемое выражение, а также открывающаяся фигурная скобка, а перед закрывающей – действие, которое должно быть выполнено при полном соответствии;
  • elseif – иначе, если. Указывать следует в случае, когда первое условие оказалось неправильным, но нужно добавить ещё одно сравнение. Также, можно записать компонент двумя словами: else if. Это приведёт к одинаковому результату. В одном условии может присутствовать в неограниченном количестве;
  • else – иначе. Срабатывает, когда остальные условия оказались ложными (недействительными).

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

Сравнение чисел типа с плавающей точкой

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

#include <iostream>

intmain()

{

    doubled1(10099.99);// должно быть 0.01

    doubled2(109.99);// должно быть 0.01

    if(d1==d2)

        std::cout<<«d1 == d2»<<«n»;

    elseif(d1>d2)

        std::cout<<«d1 > d2»<<«n»;

    elseif(d1<d2)

        std::cout<<«d1 < d2»<<«n»;

    return0;

}

Вот так раз:

d1 > d2

В вышеприведенной программе d1 = 0.0100000000000005116, а d2 = 0.0099999999999997868. Значения обоих этих чисел очень близки к 0.1, но d1 больше d2. Они не равны.

Иногда сравнение чисел типа с плавающей точкой бывает неизбежным. В таком случае следует использовать операторы >, <, >= и <= только если значения этих чисел сильно отличаются друг от друга. А вот если два операнда почти равны, то результат уже может быть неожиданный. В вышеприведенном примере последствия неправильного результата незначительны, а вот с оператором равенства дела обстоят хуже, так как даже при самой маленькой неточности результат сразу меняется на противоположный ожидаемому. Не рекомендуется использовать операторы == или != с числами типа с плавающей точкой. Вместо них следует использовать функцию, которая вычисляет, насколько эквивалентны эти два значения. Если разницей между ними можно пренебречь, то мы считаем их равными. Значение разницы между числами, которой можно пренебречь, называется эпсилоном. Оно, обычно, небольшое (например, 0.0000001).

Очень часто начинающие разработчики пытаются писать свои собственные функции определения равенства чисел:

#include <cmath> // для функции fabs()

boolisAlmostEqual(doublea,doubleb,doubleepsilon)

{

    // Если разница между a и b меньше значения эпсилона, то тогда a и b можно считать равными

    returnfabs(ab)<=epsilon;

}

Примечание: Функция fabs() — это функция из заголовочного файла cmath, которая возвращает абсолютное значение (модуль) параметра. fabs(а − b) возвращает положительное число как разницу между а и b.

Функция isAlmostEqual() из примера, приведенного выше, сравнивает разницу (a − b) и эпсилон, вычисляя, таким образом, можно ли считать эти числа равными. Если разница между а и b очень мала, то функция возвращает true.

Хоть это и рабочий вариант, но он не идеален. Эпсилон 0.00001 подходит для чисел около 1.0, но будет слишком большим для чисел типа 0.0000001 и слишком малым для чисел типа 10000. Это означает, что каждый раз при вызове функции нам нужно будет выбирать наиболее соответствующий входным данным функции эпсилон.

Дональд Кнут, известный учёный, предложил следующий способ в своей книге «Искусство программирования, том 2: Получисленные алгоритмы» (1968):

#include <cmath> // для функции fabs()

// Возвращаем true, если разница между a и b в пределах процента эпсилона

boolapproximatelyEqual(doublea,doubleb,doubleepsilon)

{

    returnfabs(ab)<=((fabs(a)<fabs(b)?fabs(b):fabs(a))*epsilon);

}

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

Рассмотрим детально, как работает функция approximatelyEqual(). Слева от оператора <= абсолютное значение (а − b) сообщает нам разницу между а и b (положительное число). Справа от <= нам нужно вычислить эпсилон, т.е. наибольшее значение разности чисел, которое мы готовы принять. Для этого алгоритм выбирает большее из чисел а и b (как приблизительный показатель общей величины чисел), а затем умножает его на эпсилон. В этой функции эпсилон представляет собой процентное соотношение. Например, если разница между числами а и b находится в пределах 1% (больше или меньше), то мы вводим эпсилон 1% (1% = 1/100 = 0.01). Его значение можно легко регулировать, в зависимости от обстоятельств (например, 0.01% = эпсилон 0.0001). Чтобы сделать неравенство (!=) вместо равенства — просто вызовите эту функцию, используя логический оператор НЕ (!), чтобы перевернуть результат:

if(!approximatelyEqual(a,b,0.001))

    std::cout<<a<<» is not equal to «<<b<<«n»;

Но и функция approximatelyEqual() тоже не идеальна, особенно, когда дело доходит до чисел, близких к нулю:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

#include <iostream>

#include <cmath> // для функции fabs()

// Возвращаем true, если разница между a и b в пределах процента эпсилона

boolapproximatelyEqual(doublea,doubleb,doubleepsilon)

{

returnfabs(ab)<=((fabs(a)<fabs(b)?fabs(b):fabs(a))*epsilon);

}

intmain()

{

// Значение a очень близко к 1.0, но, из-за ошибок округления, чуть меньше 1.0

doublea=0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1;

// Во-первых, давайте сравним значение a (почти 1.0) с 1.0

std::cout<<approximatelyEqual(a,1.0,1e8)<<«n»;

// Во-вторых, давайте сравним значение a — 1.0 (почти 0.0) с 0.0

std::cout<<approximatelyEqual(a1.0,0.0,1e8)<<«n»;

}

Возможно, вы удивитесь, но результат:

1
0

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

Но и этого можно избежать, используя как абсолютный эпсилон (то, что мы делали в первом способе), так и относительный (способ Кнута) вместе:

// Возвращаем true, если разница между a и b меньше absEpsilon или в пределах relEpsilon

boolapproximatelyEqualAbsRel(doublea,doubleb,doubleabsEpsilon,doublerelEpsilon)

{

    // Проверяем числа на равенство их друг другу — это нужно в тех случаях, когда сравниваемые числа являются нулевыми или «около нуля»

    doublediff=fabs(ab);

    if(diff<=absEpsilon)

        returntrue;

    // В противном случае возвращаемся к алгоритму Кнута

    returndiff<=((fabs(a)<fabs(b)?fabs(b):fabs(a))*relEpsilon);

}

Здесь мы добавили новый параметр — absEpsilon. Сначала мы сравниваем а и b с absEpsilon, который должен быть задан как очень маленькое число (например, 1e-12). Таким образом, мы решаем случаи, когда а и b — нулевые значения или близки к нулю. Если это не так, то мы возвращаемся к алгоритму Кнута.

Протестируем:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

#include <iostream>

#include <cmath> // для функции fabs()

// Возвращаем true, если разница между a и b в пределах процента эпсилона

boolapproximatelyEqual(doublea,doubleb,doubleepsilon)

{

returnfabs(ab)<=((fabs(a)<fabs(b)?fabs(b):fabs(a))*epsilon);

}

// Возвращаем true, если разница между a и b меньше absEpsilon или в пределах relEpsilon

boolapproximatelyEqualAbsRel(doublea,doubleb,doubleabsEpsilon,doublerelEpsilon)

{

// Проверяем числа на равенство их друг другу — это нужно в случаях, когда сравниваемые числа являются нулевыми или около нуля

doublediff=fabs(ab);

if(diff<=absEpsilon)

returntrue;

// В противном случае, возвращаемся к алгоритму Кнута

returndiff<=((fabs(a)<fabs(b)?fabs(b):fabs(a))*relEpsilon);

}

intmain()

{

// Значение a очень близко к 1.0, но, из-за ошибок округления, чуть меньше 1.0

doublea=0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1;

std::cout<<approximatelyEqual(a,1.0,1e8)<<«n»;     // сравниваем «почти 1.0» с 1.0

std::cout<<approximatelyEqual(a1.0,0.0,1e8)<<«n»;// сравниваем «почти 0.0» с 0.0

std::cout<<approximatelyEqualAbsRel(a1.0,0.0,1e12,1e8)<<«n»;// сравниваем «почти 0.0» с 0.0

}

Результат:

1
0
1

С удачно подобранным absEpsilon, функция approximatelyEqualAbsRel() обрабатывает близкие к нулю и нулевые значения корректно.

Сравнение чисел типа с плавающей точкой — сложная тема, и нет одного идеального алгоритма, который подойдет в любой ситуации. Однако для большинства случаев, с которыми вы будете сталкиваться, функции approximatelyEqualAbsRel() должно быть достаточно.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4
Звёзд: 5

(

334

оценок, среднее:

4,79

из 5)

loading.gif

Загрузка…

Оператор «меньше чем» <

Оператор < возвращает true, если его левый операнд меньше правого. В противном случае возвращается false:

Console.WriteLine(7.0 < 5.1); // output: FalseConsole.WriteLine(5.1 < 5.1); // output: FalseConsole.WriteLine(0.0 < 5.1); // output: TrueConsole.WriteLine(double.NaN < 5.1); // output: FalseConsole.WriteLine(double.NaN >= 5.1); // output: False

Оператор []=

Короткий оператор добавления нового элемента в массив. Он работает так, как вы и ожидаете — добавляет элемент справа в массив слева.

$array []= ‘element’;

В самом деле, это намного элегантнее, чем $array[] = ‘element’;. Некоторые тесты показывают, что это намного быстрее, в то время как другие наоборот, что это намного медленнее. Как обычно, посмотрите сами, подходит ли данный оператор вам, прежде чем делать ставку на производительность подобным трюком.

К сожалению, в официальном руководстве нет ни слова об этой замечательной возможности.

Арифметические операторы  в PHP.

Начнём с арифметический операторов:

Альтернативный синтаксис

Если планируется работать с выводом данных, которые содержат кавычки, скобки и прочие компоненты, способные конфликтовать с backend-кодом, рекомендуется соблюдать синтаксис, отличающийся от привычного для PHP.

Несмотря на существование, пользоваться им необязательно – достаточно экранировать упомянутые выше знаки добавлением обратной косой черты () перед каждой из них, однако это действие займёт особо большое время при попытках вывести большой фрагмент кода.Совмещать несколько синтаксисов в одном блоке, располагающемся между <?и ?>, запрещено.

Операторы сравнения  в PHP.

Операторы сравнения относятся к логическим операторам, и применяются для сравнения переменных. Массивы и объекты с их помощью сравнивать нельзя.

  • Тернарный оператор

    Использование этой особенности PHP спорно, поскольку помимо обеспечиваемой ею экономии времени на написании производится ухудшение читаемости кода. Но не стоит переживать – тернарный оператор эффективен для небольших сравнений и записей. Он представляет собой сокращённую форму if-elseif-else.
    Подробнее оператор описан в разделе примеров.

    [править] Ссылки

    • http://www.php.su/learnphp/operators/?compar

    Оператор нулевого коалесцирования

    Крупное обновление языка, названное PHP7, принесло новый оператор, записываемый двумя знаками вопроса (??)и, аналогично предыдущему, призванный сократить код. Им предполагается работа с функцией isset(), которая определяет, не равна ли переменная null. Если её значение отличается от этой, будет возвращено true, иначе – false.

    Безумие оператора PHP

    Операторы PHP — аккуратные и эффективные. Мы надеемся, что эти менее известные операторы научили вас кое-чему в PHP.

    Проверьте приведённые примеры кода: все они работают в PHP 7.2.5, кроме «звезды смерти». Они могут иметь некоторые предварительные условия, поэтому обязательно прочитайте документацию перед их использованием.

    Ссылки по теме

    • http://pythontutor.ru/lessons/ifelse/
    • http://pythonicway.com/python-conditionals
  • Понравилась статья? Поделиться с друзьями:
    Добавить комментарий

    ;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: