Список операторов
В следующей таблице перечислены все побитовые операторы.
Далее операторы разобраны более подробно.
Оператор | Использование | Описание |
---|---|---|
Побитовое И (AND) | Ставит 1 на бит результата, для которого соответствующие биты операндов равны 1. | |
Побитовое ИЛИ (OR) | Ставит 1 на бит результата, для которого хотя бы один из соответствующих битов операндов равен 1. | |
Побитовое исключающее ИЛИ (XOR) | Ставит 1 на бит результата, для которого только один из соответствующих битов операндов равен 1 (но не оба). | |
Побитовое НЕ (NOT) | Заменяет каждый бит операнда на противоположный. | |
Левый сдвиг | Сдвигает двоичное представление на битов влево, добавляя справа нули. | |
Правый сдвиг, переносящий знак | Сдвигает двоичное представление на битов вправо, отбрасывая сдвигаемые биты. | |
Правый сдвиг с заполнением нулями | Сдвигает двоичное представление на битов вправо, отбрасывая сдвигаемые биты и добавляя нули слева. |
Побитовые операторы работают следующим образом:
- Операнды преобразуются в 32-битные целые числа, представленные последовательностью битов. Дробная часть, если она есть, отбрасывается.
- Для бинарных операторов – каждый бит в первом операнде рассматривается вместе с соответствующим битом второго операнда: первый бит с первым, второй со вторым и т.п. Оператор применяется к каждой паре бит, давая соответствующий бит результата.
- Получившаяся в результате последовательность бит интерпретируется как обычное число.
Посмотрим, как работают операторы, на примерах.
Вспомогательные функции parseInt, toString
Для удобной работы с примерами в этой статье, если вы захотите протестировать что-то в консоли, пригодятся две функции.
- – переводит строку с двоичной записью числа в число.
- – получает для числа запись в 2-ной системе в виде строки.
Например:
Без них перевод в двоичную систему и обратно был бы куда менее удобен.
Более подробно они разбираются в главе Числа.
Формат 32-битного целого числа со знаком
Побитовые операторы в JavaScript работают с 32-битными целыми числами в их двоичном представлении.
Это представление называется «32-битное целое со знаком, старшим битом слева и дополнением до двойки».
Разберём, как устроены числа внутри подробнее, это необходимо знать для битовых операций с ними.
Что такое двоичная система счисления, вам, надеюсь, уже известно. При разборе побитовых операций мы будем обсуждать именно двоичное представление чисел, из 32 бит.
Старший бит слева – это научное название для самого обычного порядка записи цифр (от большего разряда к меньшему)
При этом, если больший разряд отсутствует, то соответствующий бит равен нулю.
Примеры представления чисел в двоичной системе:
Обратите внимание, каждое число состоит ровно из 32-битов.
Дополнение до двойки – это название способа поддержки отрицательных чисел.
Двоичный вид числа, обратного данному (например, и ) получается путём обращения всех битов с прибавлением 1.
То есть, нули заменяются на единицы, единицы – на нули и к числу прибавляется. Получается внутреннее представление того же числа, но со знаком минус.
Например, вот число :
Чтобы получить , первый шаг – обратить биты числа: заменить на , а на :
Второй шаг – к полученному двоичному числу прибавить единицу, обычным двоичным сложением: .
Итак, мы получили:
Принцип дополнения до двойки делит все двоичные представления на два множества: если крайний-левый бит равен – число положительное, если – число отрицательное
Поэтому этот бит называется знаковым битом.
Преобразование Int в двоичный код Преобразование Int в двоичный код
1.1 Этот пример Java пытается преобразовать в двоичное строковое представление.
int input = 10; String result = Integer.toBinaryString(input); System.out.println(result); // 1010
Выход
1010
1.2 Вывод – это отсутствие нулевых заполнений, и мы можем использовать и , чтобы улучшить или красиво напечатать двоичную строку.
int input = 10; String result = Integer.toBinaryString(input); String resultWithPadding = String.format("%32s", result).replaceAll(" ", "0"); // 32-bit Integer System.out.println(resultWithPadding);
Выход
00000000000000000000000000001010
1.3 Этот пример Java дополнительно улучшает двоичный формат с разделителем.
package com.mkyong.crypto.bytes; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class IntToBinaryExample1 { public static void main(String[] args) { int input = 10; String result = Integer.toBinaryString(input); String resultWithPadding = String.format("%32s", result).replaceAll(" ", "0"); System.out.println(resultWithPadding); System.out.println(printBinary(resultWithPadding, 8, " | ")); // 00000000 | 00000000 | 00000000 | 00001010 System.out.println(printBinary(resultWithPadding, 4, " ")); // 0000 0000 0000 0000 0000 0000 0000 1010 } public static String printBinary(String binary, int blockSize, String separator) { List result = new ArrayList<>(); int index = 0; while (index < binary.length()) { result.add(binary.substring(index, Math.min(index + blockSize, binary.length()))); index += blockSize; } return result.stream().collect(Collectors.joining(separator)); } }
Выход
00000000000000000000000000001010 00000000 | 00000000 | 00000000 | 00001010 0000 0000 0000 0000 0000 0000 0000 1010
Округление
Одна из часто используемых операций при работе с числами – это округление.
В JavaScript есть несколько встроенных функций для работы с округлением:
- Округление в меньшую сторону: становится , а — .
- Округление в большую сторону: становится , а — .
- Округление до ближайшего целого: становится , — , а — .
- (не поддерживается в Internet Explorer)
- Производит удаление дробной части без округления: становится , а — .
Ниже представлена таблица с различиями между функциями округления:
Эти функции охватывают все возможные способы обработки десятичной части. Что если нам надо округлить число до количества цифр в дробной части?
Например, у нас есть и мы хотим округлить число до 2-х знаков после запятой, оставить только .
Есть два пути решения:
Умножить и разделить.
Например, чтобы округлить число до второго знака после запятой, мы можем умножить число на , вызвать функцию округления и разделить обратно.
Метод toFixed(n) округляет число до знаков после запятой и возвращает строковое представление результата.
Округляет значение до ближайшего числа, как в большую, так и в меньшую сторону, аналогично методу :
Обратите внимание, что результатом является строка. Если десятичная часть короче, чем необходима, будут добавлены нули в конец строки:
Мы можем преобразовать полученное значение в число, используя унарный оператор или , пример с унарным оператором: .
Неточные вычисления
Внутри JavaScript число представлено в виде 64-битного формата IEEE-754. Для хранения числа используется 64 бита: 52 из них используется для хранения цифр, 11 из них для хранения положения десятичной точки (если число целое, то хранится 0), и один бит отведён на хранение знака.
Если число слишком большое, оно переполнит 64-битное хранилище, JavaScript вернёт бесконечность:
Наиболее часто встречающаяся ошибка при работе с числами в JavaScript – это потеря точности.
Посмотрите на это (неверное!) сравнение:
Да-да, сумма и не равна .
Странно! Что тогда, если не ?
Но почему это происходит?
Число хранится в памяти в бинарной форме, как последовательность бит – единиц и нулей. Но дроби, такие как , , которые выглядят довольно просто в десятичной системе счисления, на самом деле являются бесконечной дробью в двоичной форме.
Другими словами, что такое ? Это единица делённая на десять — , одна десятая. В десятичной системе счисления такие числа легко представимы, по сравнению с одной третьей: , которая становится бесконечной дробью .
Деление на гарантированно хорошо работает в десятичной системе, но деление на – нет. По той же причине и в двоичной системе счисления, деление на обязательно сработает, а становится бесконечной дробью.
В JavaScript нет возможности для хранения точных значений 0.1 или 0.2, используя двоичную систему, точно также, как нет возможности хранить одну третью в десятичной системе счисления.
Числовой формат IEEE-754 решает эту проблему путём округления до ближайшего возможного числа. Правила округления обычно не позволяют нам увидеть эту «крошечную потерю точности», но она существует.
Пример:
И когда мы суммируем 2 числа, их «неточности» тоже суммируются.
Вот почему – это не совсем .
Не только в JavaScript
Справедливости ради заметим, что ошибка в точности вычислений для чисел с плавающей точкой сохраняется в любом другом языке, где используется формат IEEE 754, включая PHP, Java, C, Perl, Ruby.
Можно ли обойти проблему? Конечно, наиболее надёжный способ — это округлить результат используя метод toFixed(n):
Также можно временно умножить число на 100 (или на большее), чтобы привести его к целому, выполнить математические действия, а после разделить обратно. Суммируя целые числа, мы уменьшаем погрешность, но она все равно появляется при финальном делении:
Таким образом, метод умножения/деления уменьшает погрешность, но полностью её не решает.
Забавный пример
Попробуйте выполнить его:
Причина та же – потеря точности. Из 64 бит, отведённых на число, сами цифры числа занимают до 52 бит, остальные 11 бит хранят позицию десятичной точки и один бит – знак. Так что если 52 бит не хватает на цифры, то при записи пропадут младшие разряды.
Интерпретатор не выдаст ошибку, но в результате получится «не совсем то число», что мы и видим в примере выше. Как говорится: «как смог, так записал».
Два нуля
Другим забавным следствием внутреннего представления чисел является наличие двух нулей: и .
Все потому, что знак представлен отдельным битом, так что, любое число может быть положительным и отрицательным, включая нуль.
В большинстве случаев это поведение незаметно, так как операторы в JavaScript воспринимают их одинаковыми.
parseInt и parseFloat
Для явного преобразования к числу можно использовать или . Если строка не является в точности числом, то результат будет :
Единственное исключение — это пробелы в начале строки и в конце, они игнорируются.
В реальной жизни мы часто сталкиваемся со значениями у которых есть единица измерения, например или в CSS. Также во множестве стран символ валюты записывается после номинала . Так как нам получить числовое значение из таких строк?
Для этого есть и .
Они «читают» число из строки. Если в процессе чтения возникает ошибка, они возвращают полученное до ошибки число. Функция возвращает целое число, а возвращает число с плавающей точкой:
Функции вернут , если не смогли прочитать ни одну цифру:
Второй аргумент
Функция имеет необязательный второй параметр. Он определяет систему счисления, таким образом может также читать строки с шестнадцатеричными числами, двоичными числами и т.д.:
Преобразование сложных типов в JS
Когда дело доходит до объектов, движок сначала приводит объекты к примитивным значениям, а уже потом выполнить финальное преобразование. Как и в случае с примитивами, объект может быть преобразован всего тремя способами (численным, строковым, булевым).
Алгоритм преобразования сложных типов (в общем случае):
- Если входящее значение уже является примитивом, то оно возвращается без изменений.
- Вызывается метод toString(), если результат вызова — примитив, то вернуть его.
- Вызывается метод valueOf(), если результат вызова — примитив, то вернуть его.
- Если ни один из методов не вернул примитив — вернуть ошибку TypeError.
При численном преобразовании сначала вызывается метод valueOf(), а уже затем toString().
При строковом преобразовании — сначала происходит вызов toString(), а уже потом valueOf().
Пример
JavaScript
» + new Date // ‘Thu Mar 07 2018 21:14:50 GMT+0300’ (приведение к string)
+ new Date // 1551982490848 (приведение к number)
1 |
»+newDate// ‘Thu Mar 07 2018 21:14:50 GMT+0300’ (приведение к string) +newDate// 1551982490848 (приведение к number) |
При логическом (булевом) преобразовании любое не примитивное значение всегда приводится к true, включая пустые объекты и массивы.
Примеры:
JavaScript
[] + [] // «» («» + «» — в итоге пустая строка)
[] + // «1» («»+»1»)
1 — // 0
+ // «11» («1» + «1»)
{} + {} // «»
{} — {} // NaN
1 |
+// «» («» + «» — в итоге пустая строка) +1// «1» («»+»1») 1-1// 0 1+1// «11» («1» + «1») {}+{}// «» {}-{}// NaN |
Подробнее о преобразовании типов — . И ещё подробно .
Задачи
JavaScript
const bool = new Boolean(false); // создаем новый объект Boolean(false) — экземпляр класса
if (bool) console.log(bool); // т.к. Boolean(false) — объект, то он будет приведен к true, значит, if(bool) // true, а консоль выведет // Boolean {false}
if (bool == false) console.log(bool); // сравнение bool=Boolean(false) с false // true, а консоль приведет объект к строке и выведет // Boolean {false}
console.log(typeof null) // object (это баг JS, фактически null — примитивное значение)
new Date(0) — 0; // 0
new Array(1) + «»; // new Array(num) при вызове с единственным аргументом-числом создаёт массив данной длины, без элементов. Поэтому его нулевой элемент равен undefined, при сложении со строкой получается строка «undefined».
({}); // фигурные скобки внутри круглых – это создание пустого объекта, у него нет свойства ‘0’, т.е. значением будет undefined.
+ 1; // 11 (массив вернет строку «1», далее — конкатенация)
+ ; // 1,23,4 (массивы вернут строковые значения с запятыми)
[] + null + 1; // null1 (массив вернет пустую строку, далее — конкатенация)
`0`; // 0 (`0` – это вложенный массив внутри внешнего . Затем мы берём от него нулевой элемент, и потом ещё раз)
{} + {}; // (используется toString, в итоге складываются строковые представления объектов)
0 || «0» && {} // {} (ИЛИ вернет «0», далее «0» && {}, который вернет второй операнд — {})
1 |
constbool=newBoolean(false);// создаем новый объект Boolean(false) — экземпляр класса if(bool)console.log(bool);// т.к. Boolean(false) — объект, то он будет приведен к true, значит, if(bool) // true, а консоль выведет // Boolean {false} if(bool==false)console.log(bool);// сравнение bool=Boolean(false) с false // true, а консоль приведет объект к строке и выведет // Boolean {false} console.log(typeofnull)// object (это баг JS, фактически null — примитивное значение) newDate()-;// 0 newArray(1)+»»;// new Array(num) при вызове с единственным аргументом-числом создаёт массив данной длины, без элементов. Поэтому его нулевой элемент равен undefined, при сложении со строкой получается строка «undefined». ({});// фигурные скобки внутри круглых – это создание пустого объекта, у него нет свойства ‘0’, т.е. значением будет undefined. 1+1;// 11 (массив вернет строку «1», далее — конкатенация) 1,2+3,4;// 1,23,4 (массивы вернут строковые значения с запятыми) +null+1;// null1 (массив вернет пустую строку, далее — конкатенация) ;// 0 (`0` – это вложенный массив внутри внешнего . Затем мы берём от него нулевой элемент, и потом ещё раз) {}+{};// (используется toString, в итоге складываются строковые представления объектов) ||«»&&{}// {} (ИЛИ вернет «0», далее «0» && {}, который вернет второй операнд — {}) |
Методы округления чисел
В JavaScript имеется
встроенный объект Math, предоставляющий различные математические методы.
Здесь мы рассмотрим функции, связанные с округлением чисел. Они следующие:
-
Math.floor – округление в
меньшую сторону; -
Math.ceil – округление в
большую сторону; -
Math.round – округление до
ближайшего целого.
Например:
let dig = 1.5; let res = Math.floor(dig); console.log( res ); // 1 console.log( Math.ceil(dig) ); // 2 console.log( Math.round(1.4) ); // 1 console.log( Math.round(1.5) ); // 2
А что если мы
хотим округлить число до второго знака после запятой (до сотых)? Это можно
сделать, например, так:
let dig = 1.23456; let res = Math.round(dig*100)100; console.log( res );
Но для такой
операции в JavaScript имеется
встроенный числовой метод toFixed(n), где n – число знаков
после запятой. Наш пример можно переписать так:
console.log( dig.toFixed(2) );
Восьмеричная система
Как предложено названием, восьмеричная система основана на восьми основных цифрах, от 0 до 7. Любопытно факт состоит в том, что некоторые коренные американцы племена принимают восьмиентальную систему, потому что они считают, используя промежутки между пальцами или костяшками их закрытых кулаков (если вы хотите узнать больше об этом: Язык Юки (Пространства между пальцами) , Паменские языки (костяшки закрытых кулаков)). Процедура, используемая для преобразования числа в восьмеричной системе, аналогична тому, которое используется выше. В Python, Октальные числа идентифицируются префиксом «0O» и функция, которая используется для выполнения преобразования, называется ; Вход, конечно, является десятичным числом, который мы хотим преобразовать.
dec_to_oct = oct(57) print(dec_to_oct) # 0o71
Противоположная операция все еще может быть выполнена, используя снова функция.
oct_to_dec = int(0o71) print(oct_to_dec) # 57
Как вы можете себе представить, также можно преобразовать непосредственно из двоичного в восьмерию и наоборот. Функции в пьесе всегда одинаковы, давайте посмотрим, как преобразовать двоичный 0B100010111010 в восьмеричной системе:
bin_to_oct = oct(0b100010111010) print(bin_to_oct) # 0o4272
Вы помните, что было эквивалентным для этого номера в десятичной обозначении? Мы можем использовать Python чтобы получить ответ мгновенно; Однако результаты, которые мы получаем от таких функций, как или Выражены в формате строки, это означает, что если мы введем их в качестве входных параметров функции , Мы получаем ошибку, заявив, что Python не может преобразовать строку в число. Чтобы решить эту проблему, мы можем указать формат входного параметра следующим образом:
oct_to_dec = int(bin_to_oct, 8) print(bin_to_oct, oct_to_dec) # 0o4272 2234
В бинарном случае мы бы использовали «2».
Функция isNaN
Функция isNaN предназначена для определения того, является ли аргумент числом или может ли быть преобразован к нему. Если это так, то функция isNaN возвращает false. В противном случае она возвращает true.
isNaN(NaN); //true isNaN('25px'); //true, т.к. 20px - это не число isNaN(25.5); //false isNaN('25.5'); //false isNaN(' '); //false, т.к. пробел или неcколько пробелов преобразуется к 0 isNaN(null); //false, т.к. значение null преобразуется к 0 isNaN(true); //false, т.к. значение true преобразуется к 1 isNaN(false); //false, т.к. значение false преобразуется к 0
Если это действие нужно выполнить без приведения типа, то используйте метод Number.isNaN. Данный метод был введён в язык, начиная с ECMAScript 6.
Проверка: isFinite и isNaN
Помните эти специальные числовые значения?
- (и ) — особенное численное значение, которое ведёт себя в точности как математическая бесконечность ∞.
- представляет ошибку.
Эти числовые значения принадлежат типу , но они не являются «обычными» числами, поэтому есть функции для их проверки:
-
преобразует значение в число и проверяет является ли оно :
Нужна ли нам эта функция? Разве не можем ли мы просто сравнить ? К сожалению, нет. Значение уникально тем, что оно не является равным ни чему другому, даже самому себе:
-
преобразует аргумент в число и возвращает , если оно является обычным числом, т.е. не :
Иногда используется для проверки, содержится ли в строке число:
Помните, что пустая строка интерпретируется как во всех числовых функциях, включая.
Сравнение
Существует специальный метод Object.is, который сравнивает значения примерно как , но более надёжен в двух особых ситуациях:
- Работает с : , здесь он хорош.
- Значения и разные: , это редко используется, но технически эти значения разные.
Во всех других случаях идентичен .
Этот способ сравнения часто используется в спецификации JavaScript. Когда внутреннему алгоритму необходимо сравнить 2 значения на предмет точного совпадения, он использует (Определение ).
Двоичные числа
Двоичные числа с только один бит набор легко понять:
Двоичное представление | Десятичное значение |
---|---|
00000000000000000000000000000001 | 1 |
00000000000000000000000000000010 | 2 |
00000000000000000000000000000100 | 4 |
00000000000000000000000000001000 | 8 |
00000000000000000000000000010000 | 16 |
00000000000000000000000000100000 | 32 |
00000000000000000000000001000000 | 64 |
Установка нескольких битов показывает двоичный шаблон:
Двоичное представление | Десятичное значение |
---|---|
00000000000000000000000000000101 | 5 (4 + 1) |
00000000000000000000000000001101 | 13 (8 + 4 + 1) |
00000000000000000000000000101101 | 45 (32 + 8 + 4 + 1) |
Двоичные номера JavaScript хранятся в формате дополнения 2.
Это означает, что отрицательное число является битовым не числа плюс 1:
Двоичное представление | Десятичное значение |
---|---|
00000000000000000000000000000101 | 5 |
11111111111111111111111111111011 | -5 |
00000000000000000000000000000110 | 6 |
11111111111111111111111111111010 | -6 |
00000000000000000000000000101000 | 40 |
11111111111111111111111111011000 | -40 |
Преобразование Двоичных Чисел
В этом разделе мы узнаем, как преобразовать двоичное число в десятичный формат и наоборот. Здесь мы сначала используем встроенную функцию Java для преобразования, а затем напишем наши собственные методы для того же самого.
3.1. Десятичное или двоичное число
Целое число имеет функцию с именем в двоичную строку для преобразования десятичного числа в его двоичную строку:
@Test public void given_decimalNumber_then_convertToBinaryNumber() { assertEquals("1000", Integer.toBinaryString(8)); assertEquals("10100", Integer.toBinaryString(20)); }
Теперь мы можем попытаться написать вашу собственную логику для этого преобразования. Прежде чем писать код, давайте сначала разберемся, как преобразовать десятичное число в двоичное.
Чтобы преобразовать десятичное число n в двоичный формат, нам нужно:
- Разделите n на 2, отметив частное q и остаток r
- Разделите q на 2, отметив его частное и остаток
- Повторяйте шаг 2, пока мы не получим 0 в качестве частного
- Объедините в обратном порядке все остатки
Давайте рассмотрим пример преобразования 6 в эквивалент двоичного формата:
- Сначала разделите 6 на 2: частное 3, остаток 0
- Затем разделите 3 на 2: частное 1, остаток 1
- И, наконец, разделите 1 на 2: частное 0, остаток 1
- 110
Давайте теперь реализуем приведенный выше алгоритм:
public Integer convertDecimalToBinary(Integer decimalNumber) { if (decimalNumber == 0) { return decimalNumber; } StringBuilder binaryNumber = new StringBuilder(); Integer quotient = decimalNumber; while (quotient > 0) { int remainder = quotient % 2; binaryNumber.append(remainder); quotient /= 2; } binaryNumber = binaryNumber.reverse(); return Integer.valueOf(binaryNumber.toString()); }
3.2. Двоичное или десятичное число
Для анализа двоичной строки класс Integer предоставляет функцию parseInt :
@Test public void given_binaryNumber_then_ConvertToDecimalNumber() { assertEquals(8, Integer.parseInt("1000", 2)); assertEquals(20, Integer.parseInt("10100", 2)); }
Здесь функция parseInt принимает в качестве входных данных два параметра:
- Двоичная строка, подлежащая преобразованию
- Основание или основание системы счисления, в которой должна быть преобразована входная строка
Теперь давайте попробуем написать вашу собственную логику преобразования двоичного числа в десятичное:
- Начните с крайней правой цифры
- Умножьте каждую цифру на 2^{положение} этой цифры – здесь положение самой правой цифры равно нулю, и оно увеличивается по мере того, как мы перемещаемся в левую сторону
- Добавьте результат всех умножений, чтобы получить конечное десятичное число
Еще раз, давайте посмотрим на наш метод в действии:
- Первый, 101011 = (1*2^5) + (0*2^4) + (1*2^3) + (0*2^2) + (1*2^1) + (1*2^0)
- Следующий, 101011 = (1*32) + (0*16) + (1*8) + (0*4) + (1*2) + (1*1)
- Тогда, + 0 + 8 + 0 + 2 + 1
- И, наконец,,
Давайте, наконец, закодируем описанные выше шаги:
public Integer convertBinaryToDecimal(Integer binaryNumber) { Integer decimalNumber = 0; Integer base = 1; while (binaryNumber > 0) { int lastDigit = binaryNumber % 10; binaryNumber = binaryNumber / 10; decimalNumber += lastDigit * base; base = base * 2; } return decimalNumber; }
JavaScript использует битовые операнды 32 бит
JavaScript хранит числа в виде чисел с плавающей запятой в 64 бит, но все битовые операции выполняются с двоичными номерами 32 бит.
До выполнения побитовой операции JavaScript преобразует числа в 32 битов со знаком целых чисел.
После выполнения побитовой операции результат преобразуется обратно в числа JavaScript 64 бит.
В приведенных выше примерах используются 4 бита неподписанных двоичных чисел. Из-за этого ~ 5 возвращает 10.
Поскольку JavaScript использует 32 битов со знаком целых чисел, он не вернет 10. Он вернется-6.
00000000000000000000000000000101 (5)
11111111111111111111111111111010 (~ 5 =-6)
Целое число со знаком использует крайний левый бит в качестве знака минуса.
Арифметические операции
В этом разделе мы сосредоточимся на выполнении арифметических операций с двоичными числами.
4.1. Дополнение
Точно так же, как при сложении десятичных чисел, мы начинаем добавлять числа с самой правой цифры.
При добавлении двух двоичных цифр нам нужно помнить следующие правила:
- 0 +
- 0 +
- 1 +
- 1 + 1 +
Эти правила могут быть реализованы следующим образом:
public Integer addBinaryNumber(Integer firstNum, Integer secondNum) { StringBuilder output = new StringBuilder(); int carry = 0; int temp; while (firstNum != 0 || secondNum != 0) { temp = (firstNum % 10 + secondNum % 10 + carry) % 2; output.append(temp); carry = (firstNum % 10 + secondNum % 10 + carry) / 2; firstNum = firstNum / 10; secondNum = secondNum / 10; } if (carry != 0) { output.append(carry); } return Integer.valueOf(output.reverse().toString()); }
4.2. Вычитание
Существует множество способов вычитания двоичных чисел. В этом разделе мы изучим метод дополнения для выполнения вычитания.
Давайте сначала поймем, что является дополнением к числу.
Чье-либо дополнение к числу-это число, полученное путем отрицания каждой цифры двоичного числа. Это означает, что просто замените 1 на 0 и 0 на 1 :
public Integer getOnesComplement(Integer num) { StringBuilder onesComplement = new StringBuilder(); while (num > 0) { int lastDigit = num % 10; if (lastDigit == 0) { onesComplement.append(1); } else { onesComplement.append(0); } num = num / 10; } return Integer.valueOf(onesComplement.reverse().toString()); }
Чтобы выполнить вычитание двух двоичных чисел с использованием дополнения, нам нужно:
- Вычислите дополнение единицы к подзаголовку s
- Добавить s и дополнить
- Если перенос создается на шаге 2, добавьте этот перенос в результат шага 2, чтобы получить окончательный ответ.
- Если перенос не генерируется на шаге 2, то дополнение к результату шага 2 является окончательным ответом. Но в данном случае ответ отрицательный
Давайте выполним описанные выше шаги:
public Integer substractBinaryNumber(Integer firstNum, Integer secondNum) { int onesComplement = Integer.valueOf(getOnesComplement(secondNum)); StringBuilder output = new StringBuilder(); int carry = 0; int temp; while (firstNum != 0 || onesComplement != 0) { temp = (firstNum % 10 + onesComplement % 10 + carry) % 2; output.append(temp); carry = (firstNum % 10 + onesComplement % 10 + carry) / 2; firstNum = firstNum / 10; onesComplement = onesComplement / 10; } String additionOfFirstNumAndOnesComplement = output.reverse().toString(); if (carry == 1) { return addBinaryNumber(Integer.valueOf(additionOfFirstNumAndOnesComplement), carry); } else { return getOnesComplement(Integer.valueOf(additionOfFirstNumAndOnesComplement)); } }
JavaScript учебник
JS HOMEJS IntroductionJS Where ToJS OutputJS StatementsJS SyntaxJS CommentsJS VariablesJS OperatorsJS ArithmeticJS AssignmentJS Data TypesJS FunctionsJS ObjectsJS ScopeJS EventsJS StringsJS String MethodsJS NumbersJS Number MethodsJS ArraysJS Array MethodsJS Array SortJS Array IterationJS DatesJS Date FormatsJS Date Get MethodsJS Date Set MethodsJS MathJS RandomJS BooleansJS ComparisonsJS ConditionsJS SwitchJS Loop ForJS Loop WhileJS BreakJS Type ConversionJS BitwiseJS RegExpJS ErrorsJS DebuggingJS HoistingJS Strict ModeJS this KeywordJS Style GuideJS Best PracticesJS MistakesJS PerformanceJS Reserved WordsJS VersionsJS Version ES5JS Version ES6JS JSON
Преобразование объектов в простые значения
Все объекты наследуют два метода преобразования: и .
Метод возвращает строковое представление объекта. По умолчанию он ничего интересного не возвращает:
alert({x: 1}.toString()); // ""
Некоторые типы имеют более специализированные версии метода . Например, метод у массива преобразует все его элементы в строки и затем объединяет их в одну строку, вставляя запятые между ними:
alert(.toString()); // "1,2,3"
Задача метода определена не так чётко: предполагается, что он должен преобразовать объект в представляющее его простое значение, если такое значение существует. Объекты по своей сути являются составными значениями, и большинство объектов не могут быть представлены в виде единственного простого значения, поэтому по умолчанию метод возвращает не простое значение, а ссылку на него:
alert(typeof {x:2}.valueOf()); // "object"
При преобразовании объекта в строку интерпретатор JavaScript выполняет следующие действия:
- Если объект имеет метод , интерпретатор вызывает его. Если он возвращает простое значение, интерпретатор преобразует значение в строку (если оно не является строкой) и возвращает результат преобразования.
- Если объект не имеет метода или этот метод не возвращает простое значение, то интерпретатор проверяет наличие метода . Если этот метод определён, интерпретатор вызывает его. Если он возвращает простое значение, интерпретатор преобразует это значение в строку (если оно не является строкой) и возвращает результат преобразования.
- В противном случае интерпретатор делает вывод, что ни ни не позволяют получить простое значение и возбуждает ошибку .
При преобразовании объекта в число интерпретатор выполняет те же действия, но первым пытается применить метод :
- Если объект имеет метод , возвращающий простое значение, интерпретатор преобразует (при необходимости) это значение в число и возвращает результат.
- Если объект не имеет метода или этот метод не возвращает простое значение, то интерпретатор проверяет наличие метода . Если объект имеет метод , возвращающий простое значение, интерпретатор выполняет преобразование и возвращает полученное значение.
- В противном случае интерпретатор делает вывод, что ни ни не позволяют получить простое значение и возбуждает ошибку .
Методы и доступны для чтения и записи, поэтому их можно переопределить и явно указать, что будет возвращаться при преобразовании:
var obj = {}; obj.toString = function() { return "объект"; }; alert("Это " + obj); // "Это объект"
С этой темой смотрят:
- Типы данных
- Числа
- Infinity и NaN
- Строки
- Boolean
isFinite и isNaN
Если по каким-то
причинам результатом вычислений становятся значения Infinite или NaN, то было бы
полезно иметь функции, которые бы умели «узнавать» такие выражения. Этими
функциями как раз и являются isFinite и isNaN. Например:
console.log( isNaN(NaN) ); // true console.log( isNaN("1") ); // false console.log( isNaN(2) ); // false console.log( isNaN("abc") ); // true
По аналогии
работает и вторая функция isFinit:
console.log( isFinite("15") ); // true console.log( isFinite("str") ); // false, потому что специальное значение: NaN console.log( isFinite(Infinity) ); // false
Как видим, она
возвращает true, если это число
и оно ограничено (не бесконечно) и false в других
случаях.
Кстати, иногда
isFinite используется для проверки: содержится ли в строке число:
let num = prompt("Enter a number", ''); if( isFinite(num) ) console.log("это число"); else console.log("это не число");
Правда, если num будет пустой
строкой, то эта функция решит, что это число 0 (так как пустая строка
приводится к числу 0). Поэтому, более точная проверка будет такой:
if( num.length > && isFinite(num) ) console.log("это число"); else console.log("это не число");