Math.floor()
Содержание:
- Что такое JavaScript?
- Number
- Способы записи числа
- Число
- Приём проектирования «Модуль»
- JavaScript
- Функции стандарта C++
- CommonJS и AMD
- JavaScript
- Сложение и вычитание
- Как мы можем включить модули?
- Инкремент/декремент
- Сравнение
- Операторы и операнды
- Присваивание
- Поразрядные операции
- Почему нужно использовать модули в JavaScript?
Что такое JavaScript?
Изначально JavaScript был создан, чтобы «сделать веб-страницы живыми».
Программы на этом языке называются скриптами. Они могут встраиваться в HTML и выполняться автоматически при загрузке веб-страницы.
Скрипты распространяются и выполняются, как простой текст. Им не нужна специальная подготовка или компиляция для запуска.
Это отличает JavaScript от другого языка – Java.
Почему JavaScript?
Когда JavaScript создавался, у него было другое имя – «LiveScript». Однако, язык Java был очень популярен в то время, и было решено, что позиционирование JavaScript как «младшего брата» Java будет полезно.
Со временем JavaScript стал полностью независимым языком со своей собственной спецификацией, называющейся ECMAScript, и сейчас не имеет никакого отношения к Java.
Сегодня JavaScript может выполняться не только в браузере, но и на сервере или на любом другом устройстве, которое имеет специальную программу, называющуюся «движком» JavaScript.
У браузера есть собственный движок, который иногда называют «виртуальная машина JavaScript».
Разные движки имеют разные «кодовые имена». Например:
- V8 – в Chrome и Opera.
- SpiderMonkey – в Firefox.
- …Ещё есть «Trident» и «Chakra» для разных версий IE, «ChakraCore» для Microsoft Edge, «Nitro» и «SquirrelFish» для Safari и т.д.
Эти названия полезно знать, так как они часто используются в статьях для разработчиков. Мы тоже будем их использовать. Например, если «функциональность X поддерживается V8», тогда «Х», скорее всего, работает в Chrome и Opera.
Как работают движки?
Движки сложны. Но основы понять легко.
- Движок (встроенный, если это браузер) читает («парсит») текст скрипта.
- Затем он преобразует («компилирует») скрипт в машинный язык.
- После этого машинный код запускается и работает достаточно быстро.
Движок применяет оптимизации на каждом этапе. Он даже просматривает скомпилированный скрипт во время его работы, анализируя проходящие через него данные, и применяет оптимизации к машинному коду, полагаясь на полученные знания. В результате скрипты работают очень быстро.
Number
Все числа хранятся в формате float64, т.е 8 байт с плавающей точкой. В этом формате не всегда возможны точные вычисления.
Например,
alert(0.1+0.2) // выведет не 0.3!
При операциях с Number — никогда не происходят ошибки. Зато могут быть возвращены специальные значения:
- 1/0
- Number.POSITIVE_INFINITY (плюс бесконечность)
- -1/0
- Number.NEGATIVE_INFINITY (минус бесконечность)
- Number(“something”)
- NaN (Not-a-Number, результат ошибочной операции)
Бесконечность бывает полезно использовать в обычном коде. Например, положительная бесконечность Number.POSITIVE_INFINITY больше любого Number, и даже больше самой себя.
NaN — особый результат.
- Любая математическая операция с NaN дает NaN:
- NaN не равен сам себе:
- Можно проверить с помощью функции isNaN:
Для этого используется метод toFixed.
0.1234.toFixed(2) = 0.12
Стандартно конвертация осуществляется вызовом Number(). Можно и попроще: +str.
// эквивалентные записи var str = "002" var a = Number(str) // 2 // нечисла превращаются в NaN +"0.1" // => 0.1 +"0.1z" // => Number.NaN
Кроме жесткой конвертации есть и более мягкая фильтрация в число:
// обрезается все после числа parseFloat("0.1zf") = 0.1 parseInt("08f.4", 10) = 8 // тут числа вообще нет, поэтому NaN parseFloat("smth") = Number.NaN
parseFloat , parseInt переводят слева направо, пока это возможно. Если вообще невозможно — то NaN.
Второй аргумент parseInt — основание системы счисления. Если его нет, то система сама пытается угадать систему счисления:
parseInt("0x10") = 16 // т.к 0x обозначает 16-ричную систему parseInt("010") = 8 // т.к ведущий 0 обозначает 8-ричную систему // если хотите без сюрпризов - указывайте основание явно parseInt("010",10) = 10
Все математические функции находятся в «пакете» Math. Не то, чтобы в javascript есть реальные пакеты, просто так получилось.
- Math.floor() / Math.round() / Math.ceil() — округление
- Math.abs() — модуль числа
- Math.sin() и т.д
Способы записи числа
Представьте, что нам надо записать число 1 миллиард. Самый очевидный путь:
Но в реальной жизни мы обычно опускаем запись множества нулей, так как можно легко ошибиться. Укороченная запись может выглядеть как или для 7 миллиардов 300 миллионов. Такой принцип работает для всех больших чисел.
В JavaScript можно использовать букву , чтобы укоротить запись числа. Она добавляется к числу и заменяет указанное количество нулей:
Другими словами, производит операцию умножения числа на 1 с указанным количеством нулей.
Сейчас давайте запишем что-нибудь очень маленькое. К примеру, 1 микросекунду (одна миллионная секунды):
Записать микросекунду в укороченном виде нам поможет .
Если мы подсчитаем количество нулей , их будет 6. Естественно, верная запись .
Другими словами, отрицательное число после подразумевает деление на 1 с указанным количеством нулей:
Шестнадцатеричные числа широко используются в JavaScript для представления цветов, кодировки символов и многого другого. Естественно, есть короткий стиль записи: , после которого указывается число.
Например:
Не так часто используются двоичные и восьмеричные числа, но они также поддерживаются для двоичных и для восьмеричных:
Есть только 3 системы счисления с такой поддержкой. Для других систем счисления мы рекомендуем использовать функцию (рассмотрим позже в этой главе).
Число
Числовой тип данных () представляет как целочисленные значения, так и числа с плавающей точкой.
Существует множество операций для чисел, например, умножение , деление , сложение , вычитание и так далее.
Кроме обычных чисел, существуют так называемые «специальные числовые значения», которые относятся к этому типу данных: , и .
-
представляет собой математическую ∞. Это особое значение, которое больше любого числа.
Мы можем получить его в результате деления на ноль:
Или задать его явно:
-
означает вычислительную ошибку. Это результат неправильной или неопределённой математической операции, например:
Значение «прилипчиво». Любая операция с возвращает :
Если где-то в математическом выражении есть , то результатом вычислений с его участием будет .
Математические операции – безопасны
Математические операции в JavaScript «безопасны». Мы можем делать что угодно: делить на ноль, обращаться со строками как с числами и т.д.
Скрипт никогда не остановится с фатальной ошибкой (не «умрёт»). В худшем случае мы получим как результат выполнения.
Специальные числовые значения относятся к типу «число». Конечно, это не числа в привычном значении этого слова.
Подробнее о работе с числами мы поговорим в главе Числа.
Приём проектирования «Модуль»
Чтобы проблемы не было, всего-то нужно, чтобы у скрипта была своя собственная область видимости, чтобы его переменные не попали на страницу.
Для этого мы завернём всё его содержимое в функцию, которую тут же запустим.
Файл , оформленный как модуль:
открыть в песочнице
Этот скрипт при подключении к той же странице будет работать корректно.
Будет выводиться «Привет», а затем «Пожалуйста, нажмите на кнопку».
В примере выше объявление модуля выглядит так:
В начале и в конце стоят скобки, так как иначе была бы ошибка.
Вот, для сравнения, неверный вариант:
Ошибка при его запуске произойдёт потому, что браузер, видя ключевое слово в основном потоке кода, попытается прочитать , а здесь имени нет.
Впрочем, даже если имя поставить, то работать тоже не будет:
Дело в том, что «на месте» разрешено вызывать только .
Общее правило таково:
- Если браузер видит в основном потоке кода – он считает, что это .
- Если же идёт в составе более сложного выражения, то он считает, что это .
Для этого и нужны скобки – показать, что у нас , который по правилам JavaScript можно вызвать «на месте».
Можно показать это другим способом, например поставив перед функцией оператор:
JavaScript
JS Array
concat()
constructor
copyWithin()
entries()
every()
fill()
filter()
find()
findIndex()
forEach()
from()
includes()
indexOf()
isArray()
join()
keys()
length
lastIndexOf()
map()
pop()
prototype
push()
reduce()
reduceRight()
reverse()
shift()
slice()
some()
sort()
splice()
toString()
unshift()
valueOf()
JS Boolean
constructor
prototype
toString()
valueOf()
JS Classes
constructor()
extends
static
super
JS Date
constructor
getDate()
getDay()
getFullYear()
getHours()
getMilliseconds()
getMinutes()
getMonth()
getSeconds()
getTime()
getTimezoneOffset()
getUTCDate()
getUTCDay()
getUTCFullYear()
getUTCHours()
getUTCMilliseconds()
getUTCMinutes()
getUTCMonth()
getUTCSeconds()
now()
parse()
prototype
setDate()
setFullYear()
setHours()
setMilliseconds()
setMinutes()
setMonth()
setSeconds()
setTime()
setUTCDate()
setUTCFullYear()
setUTCHours()
setUTCMilliseconds()
setUTCMinutes()
setUTCMonth()
setUTCSeconds()
toDateString()
toISOString()
toJSON()
toLocaleDateString()
toLocaleTimeString()
toLocaleString()
toString()
toTimeString()
toUTCString()
UTC()
valueOf()
JS Error
name
message
JS Global
decodeURI()
decodeURIComponent()
encodeURI()
encodeURIComponent()
escape()
eval()
Infinity
isFinite()
isNaN()
NaN
Number()
parseFloat()
parseInt()
String()
undefined
unescape()
JS JSON
parse()
stringify()
JS Math
abs()
acos()
acosh()
asin()
asinh()
atan()
atan2()
atanh()
cbrt()
ceil()
cos()
cosh()
E
exp()
floor()
LN2
LN10
log()
LOG2E
LOG10E
max()
min()
PI
pow()
random()
round()
sin()
sqrt()
SQRT1_2
SQRT2
tan()
tanh()
trunc()
JS Number
constructor
isFinite()
isInteger()
isNaN()
isSafeInteger()
MAX_VALUE
MIN_VALUE
NEGATIVE_INFINITY
NaN
POSITIVE_INFINITY
prototype
toExponential()
toFixed()
toLocaleString()
toPrecision()
toString()
valueOf()
JS OperatorsJS RegExp
constructor
compile()
exec()
g
global
i
ignoreCase
lastIndex
m
multiline
n+
n*
n?
n{X}
n{X,Y}
n{X,}
n$
^n
?=n
?!n
source
test()
toString()
(x|y)
.
\w
\W
\d
\D
\s
\S
\b
\B
\0
\n
\f
\r
\t
\v
\xxx
\xdd
\uxxxx
JS Statements
break
class
continue
debugger
do…while
for
for…in
for…of
function
if…else
return
switch
throw
try…catch
var
while
JS String
charAt()
charCodeAt()
concat()
constructor
endsWith()
fromCharCode()
includes()
indexOf()
lastIndexOf()
length
localeCompare()
match()
prototype
repeat()
replace()
search()
slice()
split()
startsWith()
substr()
substring()
toLocaleLowerCase()
toLocaleUpperCase()
toLowerCase()
toString()
toUpperCase()
trim()
valueOf()
Функции стандарта C++
Имя | Описание |
---|---|
гиперболический ареакосинус | |
гиперболический ареасинус | |
гиперболический ареатангенс | |
кубический корень | |
возвращает величину, абсолютное значение которой равно x, но знак которой соответствует знаку y | |
функция ошибок | |
дополнительная функция ошибок | |
значение числа 2, возведённого в степень x, 2x | |
значение функции ex − 1 | |
вычисление положительной разницы между x и y, fmax(x−y, 0) | |
значение функции (x * y) + z (см. FMA) | |
наибольшее значение среди x и y | |
наименьшее значение среди x и y | |
гипотенуза, sqrt(x² + y²) | |
экспонента числа с плавающей точкой, конвертированная в | |
натуральный логарифм абсолютного значения гамма-функции | |
округление до ближайшего целого (возвращает ) | |
округление до ближайшего целого (возвращает ) | |
округление до ближайшего целого в направлении от нуля (возвращает ) | |
округление до ближайшего целого в направлении от нуля (возвращает ) | |
натуральный логарифм 1 + x | |
логарифм по основанию 2 | |
целочисленная часть логарифма x по основанию 2 | |
возвращает нечисловое значение ‘Not a Number’ | |
округление аргумента до целого значения в формате числа с плавающей точкой | |
следующий ближайшее представимое для x (по направлению к y) | |
то же, что и , но y имеет тип | |
вычисляет остаток от деления согласно стандарту IEC 60559 | |
то же, что и , но сохраняет коэффициент по указателю p (как ) | |
округление до целого (возвращает ) с вызовом ошибки , если результат отличается от аргумента. | |
округление до целого (возвращает ) | |
x * n (n is ) | |
x * n (n is ) | |
гамма-функция | |
отбрасывание дробной части |
CommonJS и AMD
Подходы выше имеют одну общую черту: используют одну глобальную переменную для обертки кода в функцию, создавая таким образом пространство имен через замыкание.
Хотя каждый подход эффективен по своему, они имеют свои недостатки.
Во-первых, вы должны знать правильный порядок подключения зависимостей.
Допустим, вы подключаете , который имеет зависимостью , поэтому теги подключения скриптов должны идти в соответствующем порядке.
Еще одним недостатком является то, что они могут занимать одно пространство имен. Например, два ваших модуля могут иметь одинаковые имена или вам нужно подключить две версии вашего модуля.
Можем ли мы подключить интерфейсы модулей не проходя через глобальную область вилимости? Ответ — да.
Есть два популярных и хорошо реализованных подхода: CommonJS и AMD
JavaScript
JS Array
concat()
constructor
copyWithin()
entries()
every()
fill()
filter()
find()
findIndex()
forEach()
from()
includes()
indexOf()
isArray()
join()
keys()
length
lastIndexOf()
map()
pop()
prototype
push()
reduce()
reduceRight()
reverse()
shift()
slice()
some()
sort()
splice()
toString()
unshift()
valueOf()
JS Boolean
constructor
prototype
toString()
valueOf()
JS Classes
constructor()
extends
static
super
JS Date
constructor
getDate()
getDay()
getFullYear()
getHours()
getMilliseconds()
getMinutes()
getMonth()
getSeconds()
getTime()
getTimezoneOffset()
getUTCDate()
getUTCDay()
getUTCFullYear()
getUTCHours()
getUTCMilliseconds()
getUTCMinutes()
getUTCMonth()
getUTCSeconds()
now()
parse()
prototype
setDate()
setFullYear()
setHours()
setMilliseconds()
setMinutes()
setMonth()
setSeconds()
setTime()
setUTCDate()
setUTCFullYear()
setUTCHours()
setUTCMilliseconds()
setUTCMinutes()
setUTCMonth()
setUTCSeconds()
toDateString()
toISOString()
toJSON()
toLocaleDateString()
toLocaleTimeString()
toLocaleString()
toString()
toTimeString()
toUTCString()
UTC()
valueOf()
JS Error
name
message
JS Global
decodeURI()
decodeURIComponent()
encodeURI()
encodeURIComponent()
escape()
eval()
Infinity
isFinite()
isNaN()
NaN
Number()
parseFloat()
parseInt()
String()
undefined
unescape()
JS JSON
parse()
stringify()
JS Math
abs()
acos()
acosh()
asin()
asinh()
atan()
atan2()
atanh()
cbrt()
ceil()
cos()
cosh()
E
exp()
floor()
LN2
LN10
log()
LOG2E
LOG10E
max()
min()
PI
pow()
random()
round()
sin()
sqrt()
SQRT1_2
SQRT2
tan()
tanh()
trunc()
JS Number
constructor
isFinite()
isInteger()
isNaN()
isSafeInteger()
MAX_VALUE
MIN_VALUE
NEGATIVE_INFINITY
NaN
POSITIVE_INFINITY
prototype
toExponential()
toFixed()
toLocaleString()
toPrecision()
toString()
valueOf()
JS OperatorsJS RegExp
constructor
compile()
exec()
g
global
i
ignoreCase
lastIndex
m
multiline
n+
n*
n?
n{X}
n{X,Y}
n{X,}
n$
^n
?=n
?!n
source
test()
toString()
(x|y)
.
\w
\W
\d
\D
\s
\S
\b
\B
\0
\n
\f
\r
\t
\v
\xxx
\xdd
\uxxxx
JS Statements
break
class
continue
debugger
do…while
for
for…in
for…of
function
if…else
return
switch
throw
try…catch
var
while
JS String
charAt()
charCodeAt()
concat()
constructor
endsWith()
fromCharCode()
includes()
indexOf()
lastIndexOf()
length
localeCompare()
match()
prototype
repeat()
replace()
search()
slice()
split()
startsWith()
substr()
substring()
toLocaleLowerCase()
toLocaleUpperCase()
toLowerCase()
toString()
toUpperCase()
trim()
valueOf()
Сложение и вычитание
Операторы сложения и вычитания доступны в JavaScript и могут использоваться для нахождения суммы и разности числовых значений. JavaScript имеет встроенный калькулятор, а математические операции могут выполняться непосредственно в консоли.
Знак плюса позволяет складывать числа, например:
Помимо операций с простыми числами JavaScript позволяет присваивать числа переменным и выполнять с ними вычисления. Для примера можно присвоить числовые значения переменным x и y, а результат поместить в z.
Символ минус позволяет вычитать числа или выполнять операции с переменными:
Также можно складывать и вычитать отрицательные числа и числа с плавающей запятой.
В JavaScript есть одна интересная особенность, которую следует учитывать и знать, — это результат сложения числа и строки. Мы знаем, что 1 + 1 должно равняться 2, но это уравнение выдаст неожиданный результат.
Вместо сложения чисел JavaScript преобразует все выражение в строки и объединяет их
Важно быть осторожным с динамической типизацией JavaScript, поскольку она может иметь нежелательные результаты
Сложение и вычитание в JavaScript часто используются для прокрутки панели навигации.
В этом случае панель будет прокручиваться на 60 пикселей от id.
Как мы можем включить модули?
Шаблон Модуль
Шаблон модуль иммитирует концепцию классов (поскольку JavaScript не поддерживает классы нативно). Мы можем хрранить как публичные, так и приватные методы и переменные внутри одного объекта — подобно тому как классы используются в других языках, таких как Java или Python. Это позволяет создавать общедоступный API для публичных методов, в то же время инкапсулируя приватные методы и переменные внутри области замыкания.
уществует несколько способов, чтобы написать паттерн Модуль. В первом примере я использую анонимное замыкание. Это поможет нам достич цели, обернув весь код в анонимную функцию. (В JavaScript функции это единственный способ создать новую область видимости).
Пример 1: Анонимное замыкание
С помощью этой конструкции, наша анонимная функция имеет свою собственную область видимости или замыкание, функция сразу же выполняется. Это позволяет нам скрыть переменные из глобальной области видимости.
Плюсы этого подхода в том, что вы можете использовать локальные переменные внутри функции без опасения, что они перезапишут глобальные переменные.
Обратите внимание на необходимость круглых скобок вокруг анонимной функции, так как они позволяют вызвать функцию сразу после ее объявления
Пример 2: Глобальный импорт
Другой популярный подход, используемый библиотекой jQuery, это глобальный импорт. Он подобен вызову анонимной функции, в примере выше, отличается тем, что мы передаем глобальную переменную как параметр.
Преимущество данного подхода по сравнению с анонимным замыканием в том, что мы заранее объявляем глобальные переменные, делая их совершенно понятными для людей читающих наш код.
Пример 3: Интерфейс объекта
Еще один подход — создание модуля как автономный интерфейс объекта.
Как вы можете видеть, этот подход дает нам возможность решить какие переменные/методы мы хотим оставить приватными (такие как myGrades) и какие мы хотим сделать доступными извне через выражение return (такие как average и failing).
Этот паттерн похож на предыдущие подходы, за исключением того, что все переменные и методы изначально создаются приватными, пока явно не назначаются публичными:
Инкремент/декремент
Одной из наиболее частых операций в JavaScript, как и во многих других языках программирования, является увеличение или уменьшение переменной на единицу.
Для этого существуют даже специальные операторы:
-
Инкремент увеличивает на 1:
-
Декремент уменьшает на 1:
Важно:
Инкремент/декремент можно применить только к переменной. Попытка использовать его на значении, типа 5++, приведёт к ошибке.
Операторы и могут быть расположены не только после, но и до переменной.
- Когда оператор идёт после переменной – это «постфиксная форма»: .
- «Префиксная форма» – это когда оператор идёт перед переменной: .
Обе эти формы записи делают одно и то же: увеличивают на .
Есть ли разница между ними? Да, но увидеть её мы сможем, только если будем использовать значение, которое возвращают .
Давайте проясним этот момент. Как мы знаем, все операторы возвращают значение. Операторы инкремент/декремент не исключение. Префиксная форма возвращает новое значение, в то время как постфиксная форма возвращает старое (до увеличения/уменьшения числа).
Чтобы увидеть разницу, вот небольшой пример:
В строке префиксная форма увеличения , она возвращает новое значение . Так что покажет .
Теперь посмотрим на постфиксную форму:
В строке постфиксная форма также увеличивает , но возвращает старое значение (которое было до увеличения). Так что покажет .
Подведём итоги:
-
Если результат оператора не используется, а нужно только увеличить/уменьшить переменную – без разницы, какую форму использовать:
-
Если хочется тут же использовать результат, то нужна префиксная форма:
-
Если нужно увеличить и при этом получить значение переменной до увеличения – постфиксная форма:
Инкремент/декремент можно использовать в любых выражениях
Операторы могут также использоваться внутри выражений. Их приоритет выше, чем у арифметических операций.
Например:
Сравните с:
Хотя технически всё в порядке, такая запись обычно делает код менее читабельным. Одна строка выполняет множество действий – нехорошо.
При беглом чтении кода можно с лёгкостью пропустить такой , и будет неочевидно, что переменная увеличивается.
Лучше использовать стиль «одна строка – одно действие»:
Сравнение
- ==
- !=
- <
- >
- <=
- >=
- ===
- !==
Операторы больше-меньше также работают со строками, сравнивая их лексикографически, т.е посимвольно.
"B">"a" "bc" < "bd"
Сравнение == делается с приведением типов, а === без приведения типов, например:
0 == false // верно // но 0 !== false //типы разные
Проверка равенства осуществляется особым образом, если один из операндов — , , . Более подробно об алгоритме в этом случае можно прочитать в секции 11.9.3 стандарта ECMA-262.
Тернарный оператор. В старых парсерах javascript с ним были проблемы, надо было заключать сравнение в скобки, но в новых — вполне нормальный оператор
Операторы и операнды
Числа, в арифметической операции, называются операндами.
Операция, которая будет выполняться между двумя операндами, определяется как оператор.
Операнд | Оператор | Операнд |
---|---|---|
100 | + | 50 |
Оператор сложения складывает числа:
var x = 5;
var y = 2;
var z = x + y;
Оператор вычитание вычитает числа.
var x = 5;
var y = 2;
var z = x — y;
Оператор умножения умножает числа.
var x = 5;
var y = 2;
var z = x * y;
Оператор деления делит числа.
var x = 5;
var y = 2;
var z = x / y;
Оператор модуль возвращает остаток деления.
var x = 5;
var y = 2;
var z = x % y;
Оператор увеличения увеличивает числа.
var x = 5;
x++;
var z = x;
Оператор уменьшения уменьшения числа.
Присваивание
Давайте отметим, что в таблице приоритетов также есть оператор присваивания = . У него один из самых низких приоритетов: 3 .
Именно поэтому, когда переменной что-либо присваивают, например, x = 2 * 2 + 1 , то сначала выполнится арифметика, а уже затем произойдёт присваивание = .
Оператор | Тип оператора | А | О | Типы значений |
---|---|---|---|---|
… + … … – … … * … … / … … % … … ** … | Сложение Вычитание Умножение Деление Деление с остатком Возведение в степень | слева направо слева направо слева направо слева направо слева направо справа налево | 2 2 2 2 2 2 | число, число → число число, число → число число, число → число число, число → число число, число → число число, число → число |
Операторы: – ( вычитание ), + ( сложение ), * ( умножение ) и / ( деление ) работают точно так же, как и арифметические действия в математике. Оператор % ( деление с остатком ) возвращает остаток от деления первого операнда на второй. Результат деления с остатком будет иметь тот же знак, что и первый операнд:
Оператор ** ( возведение в степень ) имеет два операнда. Первый операнд является основанием степени, второй операнд – показателем степени, в результате оператор возвращает основание, возведённое в указанную степень:
Все математические операторы преобразуют операнды по тем же правилам, что и функция Number().
Поразрядные операции
Последнее обновление: 30.10.2018
Поразрядные операции выполняются над отдельными разрядами или битами чисел. В данных операциях в качестве операндов могут выступать только целые числа.
Каждое число имеет определенное двоичное представление. Например, число 4 в двоичной системе 100, а число 5 — 101 и так далее.
К примеру, возьмем следующие переменные:
byte b = 7; // 0000 0111 short s = 7; // 0000 0000 0000 0111
Тип byte занимает 1 байт или 8 бит, соответственно представлен 8 разрядами. Поэтому значение переменной b в двоичном коде будет
равно . Тип short занимает в памяти 2 байта или 16 бит, поэтому число данного типа будет представлено
16 разрядами. И в данном случае переменная s в двоичной системе будет иметь значение .
Для записи чисел со знаком в Java применяется дополнительный код, при котором
старший разряд является знаковым. Если его значение равно 0, то число положительное, и его двоичное представление не отличается
от представления беззнакового числа. Например, 0000 0001 в десятичной системе 1.
Если старший разряд равен 1, то мы имеем дело с отрицательным числом. Например, 1111 1111 в десятичной системе представляет -1.
Соответственно, 1111 0011 представляет -13.
Логические операции
Логические операции над числами представляют поразрядные операции. В данном случае числа рассматриваются в двоичном представлении, например, 2 в двоичной системе
равно 10 и имеет два разряда, число 7 — 111 и имеет три разряда.
-
Умножение производится поразрядно, и если у обоих операндов значения разрядов равно 1,
то операция возвращает 1, иначе возвращается число 0. Например:int a1 = 2; //010 int b1 = 5;//101 System.out.println(a1&b1); // результат 0 int a2 = 4; //100 int b2 = 5; //101 System.out.println(a2 & b2); // результат 4
В первом случае у нас два числа 2 и 5. 2 в двоичном виде представляет число 010, а 5 — 101. Поразрядное умножение чисел (0*1, 1*0, 0*1) дает результат 000.
Во втором случае у нас вместо двойки число 4, у которого в первом разряде 1, так же как и у числа 5, поэтому здесь результатом операции
(1*1, 0*0, 0 *1) = 100 будет число 4 в десятичном формате. -
(логическое сложение)
Данная операция также производится по двоичным разрядам, но теперь возвращается единица,
если хотя бы у одного числа в данном разряде имеется единица (операция «логическое ИЛИ»). Например:int a1 = 2; //010 int b1 = 5;//101 System.out.println(a1|b1); // результат 7 - 111 int a2 = 4; //100 int b2 = 5;//101 System.out.println(a2 | b2); // результат 5 - 101
-
(логическое исключающее ИЛИ)
Также эту операцию называют XOR, нередко ее применяют для простого шифрования:
int number = 45; // 1001 Значение, которое надо зашифровать - в двоичной форме 101101 int key = 102; //Ключ шифрования - в двоичной системе 1100110 int encrypt = number ^ key; //Результатом будет число 1001011 или 75 System.out.println("Зашифрованное число: " +encrypt); int decrypt = encrypt ^ key; // Результатом будет исходное число 45 System.out.println("Расшифрованное число: " + decrypt);
Здесь также производятся поразрядные операции. Если у нас значения текущего разряда у обоих чисел разные, то возвращается 1, иначе возвращается 0.
Например, результатом выражения 9^5 будет число 12. А чтобы расшифровать число, мы применяем обратную операцию к результату. -
(логическое отрицание)
Поразрядная операция, которая инвертирует все разряды числа: если значение разряда равно 1,
то оно становится равным нулю, и наоборот.byte a = 12; // 0000 1100 System.out.println(~a); // 1111 0011 или -13
Операции сдвига
Операции сдвига также производятся над разрядами чисел. Сдвиг может происходить вправо и влево.
-
— сдвигает число a влево на b разрядов. Например, выражение сдвигает число 4 (которое в двоичном
представлении 100) на один разряд влево, в результате получается число 1000 или число 8 в десятичном представлении. -
— смещает число a вправо на b разрядов. Например, сдвигает число 16
(которое в двоичной системе 10000) на один разряд вправо, то есть в итоге получается 1000 или число 8 в десятичном представлении. -
— в отличие от предыдущих типов сдвигов данная операция представляет беззнаковый сдвиг — сдвигает число a вправо на b разрядов.
Например, выражение будет равно 1073741822.
Таким образом, если исходное число, которое надо сдвинуть в ту или другую сторону, делится на два, то фактически получается умножение или деление на два.
Поэтому подобную операцию можно использовать вместо непосредственного умножения или деления на два, так как операция сдвига на аппаратном уровне менее дорогостоящая операция
в отличие от операции деления или умножения.
НазадВперед
Почему нужно использовать модули в JavaScript?
Использование модулей дает много преимуществ в пользу расширения и независимости кода. Наиболее важным, по моему мнению, является:
- Ремонтопригодность: По определению модуль автономен. Целью хорошо спроектированного модуля является максимально уменьшенить зависимости между частями кода, таким образом модуль может расти и улучшаться независимо от остального кода. Обновление модуля легче когда модуль отделен от других частей кода.
- Пространства имен: В JavaScript переменные, объявленные вне функции являются глобальными (доступными всему коду). Из-за этого нередко возникают проблемы, когда несвязанный код разделяет глобальные переменные. Это большая проблема в разработке. Как мы увидим дальше, модули помогают разделить пространства имен созданием приватных областей вилимости.
- Повторное использование: Давайте будем честны, мы все копируем код из предыдущих проектов в новые. Но представьте, что мы нашли лучший способ, чтобы написать часть кода, тогда нам придется вернуться и переписать все предыдущие куски кода. Но не тогда, когда мы используем модули.