02 - floating points
This commit is contained in:
parent
0d694aac12
commit
a38b8a7037
BIN
build/j-spec.pdf
BIN
build/j-spec.pdf
Binary file not shown.
74
j-spec.tex
74
j-spec.tex
|
@ -18,82 +18,14 @@
|
||||||
\tableofcontents
|
\tableofcontents
|
||||||
\pagestyle{plain}
|
\pagestyle{plain}
|
||||||
|
|
||||||
\newpage
|
|
||||||
%\chapter{Java Core}
|
%\chapter{Java Core}
|
||||||
|
\newpage
|
||||||
\subfile{jtc1-01a}
|
\subfile{jtc1-01a}
|
||||||
\newpage
|
\newpage
|
||||||
|
\subfile{jtc2-02a}
|
||||||
|
\newpage
|
||||||
\subfile{jtd6-11a}
|
\subfile{jtd6-11a}
|
||||||
|
|
||||||
\section{Специализация: данные и функции}
|
|
||||||
Базовые функции языка: математические операторы, условия, циклы, бинарные операторы; Данные: типы, преобразование типов, константы и переменные (примитивные, ссылочные), бинарное представление, массивы (ссылочная природа массивов, индексация, манипуляция данными); Функции: параметры, возвращаемые значения, перегрузка функций;
|
|
||||||
\subsection{Данные}
|
|
||||||
Хранение данных в Java осуществляется привычным для программиста образом: в переменных и константах. Языки программирования бывают типизированными и нетипизированными (бестиповыми).
|
|
||||||
|
|
||||||
Отсутствие типизации в основном присуще старым и низкоуровневым языкам программирования, например, Forth, некоторые ассемблеры. Все данные в таких языках считаются цепочками бит произвольной длины и, как следует из названия, не делятся на типы. Работа с ними часто труднее, и при чтении кода не всегда ясно, о каком типе переменной идет речь. При этом часто безтиповые языки работают быстрее типизированных, но описывать с их помощью большие проекты со сложными взаимосвязями довольно утомительно.
|
|
||||||
\begin{frm}
|
|
||||||
Java является языком со строгой (сильной) явной статической типизацией.
|
|
||||||
\end{frm}
|
|
||||||
Что это значит?
|
|
||||||
\begin{itemize}
|
|
||||||
\item Статическая - у каждой переменной должен быть тип и мы этот тип поменять не можем. Этому свойству противопоставляется динамическая типизация;
|
|
||||||
\item Явная - при создании переменной мы должны ей обязательно присвоить какой-то тип, явно написав это в коде. Бывают языки с неявной типизацией, например, Python;
|
|
||||||
\item Строгая(сильная) - невозможно смешивать разнотипные данные. С другой стороны, существует JavaScript, в котором запись \code{2 + true} выдаст результат \code{3}.
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
Все данные в Java делятся на две основные категории: примитивные и ссылочные.
|
|
||||||
|
|
||||||
Данные: типы, преобразование типов, константы и переменные (примитивные, ссылочные), бинарное представление, массивы (ссылочная природа массивов, индексация, манипуляция данными);
|
|
||||||
|
|
||||||
\begin{figure}[H]
|
|
||||||
\centering
|
|
||||||
\begin{tabular}{|p{17mm}|p{80mm}|p{55mm}|}
|
|
||||||
\hline
|
|
||||||
Тип & Пояснение & Диапазон \\
|
|
||||||
\hline
|
|
||||||
byte & Самый маленький из адресуемых типов, 8 бит, знаковый & [\textminus128, +127] \\
|
|
||||||
\hline
|
|
||||||
short & Тип короткого целого числа, 16 бит, знаковый & [\textminus32 768, +32 767]\\
|
|
||||||
\hline
|
|
||||||
char & Целочисленный тип для хранения символов в кодировке UTF-8, 16 бит, беззнаковый & [0, +65 535]\\
|
|
||||||
\hline
|
|
||||||
int & Основной тип целого числа, 32 бита, знаковый & [\textminus2 147 483 648, +2 147 483 647] \\
|
|
||||||
\hline
|
|
||||||
long & Тип длинного целого числа, 64 бита, знаковый & [\textminus9 223 372 036 854 775 808, +9 223 372 036 854 775 807] \\
|
|
||||||
\hline
|
|
||||||
float & Тип вещественного числа с плавающей запятой (одинарной точности, 32 бита) & \\
|
|
||||||
\hline
|
|
||||||
double & Тип вещественного числа с плавающей запятой (двойной точности, 64 бита) & \\
|
|
||||||
\hline
|
|
||||||
boolean & Логический тип данных & true, false \\
|
|
||||||
\hline
|
|
||||||
\end{tabular}
|
|
||||||
\caption{Основные типы данных в языке С}
|
|
||||||
\label{tab:types}
|
|
||||||
\end{figure}
|
|
||||||
|
|
||||||
Базовые функции языка: математические операторы, условия, циклы, бинарные операторы;
|
|
||||||
|
|
||||||
Функции: параметры, возвращаемые значения, перегрузка функций;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\subsubsection{Антипаттерн "магические числа"}
|
|
||||||
В прошлом примере мы использовали антипаттерн - плохой стиль для написания кода. Число 18 используется в коде коде без пояснений. Такой антипаттерн называется "магическое число". Рекомендуется помещать числа в константы, которые храняться в начале файла.
|
|
||||||
ADULT = 18
|
|
||||||
age = float(input('Ваш возраст: '))
|
|
||||||
how\_old = age - ADULT
|
|
||||||
print(how\_old, "лет назад ты стал совершеннолетним")
|
|
||||||
|
|
||||||
Плюсом такого подхода является возможность легко корректировать большие проекты. Представьте, что в вашем коде несколько тысяч строк, а число 18 использовалось несколько десятков раз.
|
|
||||||
● При развертывании проекта в стране, где совершеннолетием считается 21 год вы будете перечитывать весь код в поисках магических "18" и править их на "21". В случае с константой изменить число нужно в одном месте.
|
|
||||||
● Дополнительный сложности могут возникнуть, если в коде будет 18 как возраст совершеннолетия и 18 как коэффициент для рассчёт чего-либо. Теперь править кода ещё сложнее, ведь возраст изменился, а коэффициент -нет. В случае с сохранением значений в константы мы снова меняем число в одном месте.
|
|
||||||
|
|
||||||
\subsection*{Задания к семинару}
|
|
||||||
\begin{itemize}
|
|
||||||
\item Написать как можно больше вариантов функции инвертирования массива единиц и нулей за 15 минут (без ветвлений любого рода);
|
|
||||||
\item Сравнить без условий две даты, представленные в виде трёх чисел гггг-мм-дд;
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
\section{Специализация: ООП}
|
\section{Специализация: ООП}
|
||||||
Инкапсуляция: Классы и объекты (внутренние классы, вложенные классы, static, private/public, final, интерфейс взаимодействия с объектом), перечисления (создание, конструкторы перечислений, объекты перечислений, дополнительные свойства); Наследование: extends, Object (глобальное наследование), protected, преобразование типов, final; Полиморфизм: override, abstract, final;
|
Инкапсуляция: Классы и объекты (внутренние классы, вложенные классы, static, private/public, final, интерфейс взаимодействия с объектом), перечисления (создание, конструкторы перечислений, объекты перечислений, дополнительные свойства); Наследование: extends, Object (глобальное наследование), protected, преобразование типов, final; Полиморфизм: override, abstract, final;
|
||||||
%\subfile{scenarios/jc-4}
|
%\subfile{scenarios/jc-4}
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 77 KiB |
Binary file not shown.
After Width: | Height: | Size: 235 KiB |
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
Binary file not shown.
|
@ -113,7 +113,16 @@ Java является языком со \textbf{строгой} (также мо
|
||||||
|
|
||||||
\begin{frame}
|
\begin{frame}
|
||||||
\frametitle{Типы, преобразование типов}
|
\frametitle{Типы, преобразование типов}
|
||||||
целые числа
|
Бинарное (битовое) представление
|
||||||
|
\end{frame}
|
||||||
|
\note{
|
||||||
|
При разговоре о переполнении нельзя не упомянуть о том, что же именно переполняется. поговорим о единичках и ноликах. Важно помнить, что все компьютеры так или иначе работают от электричества и являются довольно примитивными по сути устройствами, которые понимают только два состояния: есть напряжение в цепи или нет.
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Типы, преобразование типов}
|
||||||
|
таблица из методички «Основные типы данных в языке Java»
|
||||||
|
целочисленные типы
|
||||||
\end{frame}
|
\end{frame}
|
||||||
\note{
|
\note{
|
||||||
целочисленных типов аж 4 и они занимают 1,2,4,8 байт соответственно. про чар, несмотря на то, что он целочисленный мы поговорим чуть позднее. с четырьмя основными целочисленными типами всё просто - значения в них могут быть только целые, никак и никогда невозможно присвоить им дробных значений, хотя и тут можно сделать оговорку и поклон в сторону арифметики с фиксированной запятой, но мы этого делать не будем, чтобы не взрывать себе мозг и не сбиваться с основной мысли. итак, целочисленные типы с диапазонами
|
целочисленных типов аж 4 и они занимают 1,2,4,8 байт соответственно. про чар, несмотря на то, что он целочисленный мы поговорим чуть позднее. с четырьмя основными целочисленными типами всё просто - значения в них могут быть только целые, никак и никогда невозможно присвоить им дробных значений, хотя и тут можно сделать оговорку и поклон в сторону арифметики с фиксированной запятой, но мы этого делать не будем, чтобы не взрывать себе мозг и не сбиваться с основной мысли. итак, целочисленные типы с диапазонами
|
||||||
|
@ -131,27 +140,134 @@ Java является языком со \textbf{строгой} (также мо
|
||||||
}
|
}
|
||||||
\newpage
|
\newpage
|
||||||
\note{
|
\note{
|
||||||
Я вот сказал, что инт самый часто используемый и внезапно подумал: а ведь чаще всего было бы достаточно шорта, например, в циклах, итерирующихся по массивам, или во временных хранениях значений, скажем, возраста человека, но всё равно все по привычке используют инт.
|
Я вот сказал, что инт самый часто используемый и внезапно подумал: а ведь чаще всего было бы достаточно шорта, например, в циклах, итерирующихся по подавляющему большинству коллекций, или при хранении значений, скажем, возраста человека, но всё равно все по привычке используют инт.
|
||||||
|
|
||||||
далее - лайвкод в котором нужно показать присвоение к байту и попытку присвоения лонга, показать предупреждения среды.
|
далее - лайвкод в котором нужно показать присвоение к байту без переполнения и попытку присвоения лонга, показать предупреждения среды.
|
||||||
|
|
||||||
как мы видим, к маленькому байту вполне успешно присваивается инт. получается, обманул, сказав, что все числа это инты? давайте посмотрим на следующий пример - попытку присвоить значение 5 млрд переменной типа лонг. помним, что в лонге можно хранить очень большие числа, но среда показывает ошибку, значит и тут наврал? давайте разбираться по порядку: если мы посмотрим на ошибку, там английскими буквами будет очень понятно написано - не могу положить такое большое значение в переменную типа инт. а это может значить только одно: справа - инт. не соврал.
|
как мы видим, к маленькому байту вполне успешно присваивается инт. получается, обманул, сказав, что все числа это инты? давайте посмотрим на следующий пример - попытку присвоить значение 5 млрд переменной типа лонг. помним, что в лонге можно хранить очень большие числа, но среда показывает ошибку, значит и тут наврал? давайте разбираться по порядку: если мы посмотрим на ошибку, там английскими буквами будет очень понятно написано - не могу положить такое большое значение в переменную типа инт. а это может значить только одно: справа - инт. не соврал. Почему большой инт без проблем присваивается к маленькому байту поговорм буквально через несколько минут, пока просто запомним, что это происходит.
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Типы, преобразование типов}
|
||||||
|
таблица из методички «Основные типы данных в языке Java»
|
||||||
|
\end{frame}
|
||||||
|
\note{
|
||||||
|
Далее речь пойдёт о том, что называется числами с плавающей запятой. в англоязычной литературе эти числа называются числа с плавающей точкой (от английского флоутин поинт), такое различие связано с тем, что в русскоязычной литературе принято отделять дробную часть числа запятой, а в европейской и американской - точкой.
|
||||||
|
|
||||||
|
Как мы видим, два из восьми типов не имеют диапазонов значений, это связано с тем, что диапазоны значений флоута и дабла заключаются не в величине возможных хранимых чисел, а в точности этих чисел после запятой. до какого знака будет сохранена точность. Говорить о числах с плавающей точкой и ничего не сказать об особенности их хранения - преступление, поэтому, отвлечёмся.
|
||||||
}
|
}
|
||||||
|
|
||||||
\begin{frame}
|
\begin{frame}
|
||||||
\frametitle{Типы, преобразование типов}
|
\frametitle{Типы, преобразование типов}
|
||||||
немного о хранении чисел с плавающей точкой
|
немного о хранении чисел с плавающей точкой
|
||||||
|
много хорошо и подробно, но на С https://habr.com/ru/post/112953/
|
||||||
|
\includegraphics[width=100mm]{../pics/jc-02-float01.png}
|
||||||
\end{frame}
|
\end{frame}
|
||||||
\note{
|
\note{
|
||||||
Диапазоны значений флоута и дабла заключаются не в величине возможных хранимых чисел, а в точности этих чисел после запятой. до какого знака будет сохранена точность.
|
Работает по стандарту IEEE 754 (1985). Для работы с числами с плавающей запятой на аппаратурном уровне к обычному процессору который находится в вашем устройстве ещё прикручивают математический сопроцессор, он нужен, чтобы постоянно вычислять эти ужасные плавающие запятые. Если попытаться уложить весь стандарт в два предложения, то получится примерно следующее: формат подразумевает три поля (знак, 8(11) разрядов поля порядка, 23(52) бита мантисса). Чтобы получить из этой битовой каши число надо $-1$ возвести в степень знака, умножить на 2 в степени порядка минус 127 и умножить на 1 + мантиссу делёную на два в степени размера мантиссы. Формула на экране, она не очень сложная. В остальном, ничего не понятно, но очень интересно, понимаю, давайте попробуем на примере.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Типы, преобразование типов}
|
||||||
|
возьмём число +0,5
|
||||||
|
\end{frame}
|
||||||
|
\note{
|
||||||
|
с ним всё довольно просто, чтобы получить $+0,5$ нужно 2 возвести в $-1$ степень. поэтому, если развернуть обратно формулу, описанную выше, в знак и мантиссу мы ничего не пишем, оставляем 0, а в порядке должно быть 126, тогда мы должны будем $-1$ возвести в 0ю степень и получить положительный знак, умножить на 2 в степени $126-127 = -1$, получив внезапно 0,5 и умножить на 1 плюс пустая мантисса, в которой по сути не очень важно, что делить, что умножать и в какие степени возводить, всё равно 0 будет. Отсюда становится очевидно, что чем сложнее мантисса и чем меньше порядок, тем более точные и интересные числа мы можем получить.
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Типы, преобразование типов}
|
||||||
|
а что если -0,15625
|
||||||
|
\end{frame}
|
||||||
|
\note{
|
||||||
|
Попробуем немного сложнее: число $-0,15625$, чтобы понять как его записывать, откинем знак, это будет единица в разряде, отвечающем за знак, и посчитаем мантиссу с порядком. представим число как положительное и будем от него последовательно отнимать числа, являющиеся отрицательными степенями двойки, чтобы получить максимально близкое к нулю значение.
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Типы, преобразование типов}
|
||||||
|
$2^{1} = 2$
|
||||||
|
|
||||||
|
$2^{0} = 1.0$
|
||||||
|
|
||||||
|
$2^{-1} = 0.5$
|
||||||
|
|
||||||
|
$2^{-2} = 0.25$
|
||||||
|
|
||||||
|
$2^{-3} = 0.125$
|
||||||
|
|
||||||
|
$2^{-4} = 0.0625$
|
||||||
|
|
||||||
|
$2^{-5} = 0.03125$
|
||||||
|
|
||||||
|
$2^{-6} = 0.015625$
|
||||||
|
|
||||||
|
$2^{-7} = 0.0078125$
|
||||||
|
|
||||||
|
$2^{-8} = 0.00390625$
|
||||||
|
\end{frame}
|
||||||
|
\note{
|
||||||
|
получается, что $-1$ и $-2$ степени отнять не получится, мы явно уходим за границу нуля, а вот $-3$ прекрасно отнимается, значит порядок будет $127-3 = 124$, осталось понять, что получается в мантиссе. видим, что оставшееся после первого вычитания число - это 2 в $-5$ степени. значит в мантиссе мы пишем 01 и остальные нули. Получится, что
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Типы, преобразование типов}
|
||||||
|
$(-1)^1 \times 2^{(124-127)} \times (1 + \frac{2097152}{2^{23}}) = 1,15652$
|
||||||
|
|
||||||
|
\vspace{1em}
|
||||||
|
|
||||||
|
$(-1)^1 \times 1,01e-3 = 1\times2^{-3} + 0\times2^{-4} + 1\times2^{-5} = 1\times0,125 + 0\times0,0625 + 1\times0,03125 = 0,125 + 0,03125 = 0,15625$.
|
||||||
|
|
||||||
|
\end{frame}
|
||||||
|
\note{
|
||||||
|
так наше число можно посчитать двумя способами: по приведённой на слайде формуле или последовательно складывая разряды мантиссы умноженные на двойку в степени порядка, уменьшая порядок на каждом шагу, как это показано на слайде.
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Типы, преобразование типов}
|
||||||
|
немного о хранении чисел с плавающей точкой
|
||||||
|
\includegraphics[width=100mm]{../pics/jc-02-float02.png}
|
||||||
|
\end{frame}
|
||||||
|
\note{
|
||||||
|
Ну, что, поковырялись в детальках и винтиках, можно коротко поговорить об особенностях чисел с плавающей точкой, а именно:
|
||||||
|
\begin{itemize}
|
||||||
|
\item в числах с плавающей точкой бывает как положительный, так и отрицательный ноль, в отличие от целых чисел, где ноль всегда положительный
|
||||||
|
\item у чисел с плавающей запятой есть огромная зона, отмеченная на слайде, которая являет собой непредставимые числа слишком большие для хранения внутри такой переменной или настолько маленькие, что мнимая единица в мантиссе отсутствует
|
||||||
|
\item в таком числе можно хранить значение бесконечности
|
||||||
|
\item при работе с такими числами появляется понятие не-числа, при этом важно помнить, что NaN != NaN, а если очень сильно постараться, можно хранить там собственные данные, но это выходит далеко за пределы курса, и используется в каких-нибудь чрезвычайно маломощных процессорах для цифровой обработки сигналов, например.
|
||||||
|
\end{itemize}
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Типы, преобразование типов}
|
||||||
|
немного о хранении чисел с плавающей точкой
|
||||||
|
\includegraphics[width=120mm]{../pics/jc-02-float03.png}
|
||||||
|
\end{frame}
|
||||||
|
\note{
|
||||||
|
у чисел с плавающей запятой могут иногда встречаться и проблемы в вычислениях, пример на слайде чрезвычайно грубый, но при работе, например, со статысячными или миллионными долями с такой проблемой вполне можно столкнуться. порядок выполнения действий может влиять на результат выполнения этих действий, что противоречит математике.
|
||||||
|
}
|
||||||
|
|
||||||
|
% \begin{frame}
|
||||||
|
% \frametitle{Типы, преобразование типов}
|
||||||
|
% немного о хранении чисел с плавающей точкой
|
||||||
|
% Арифметические проблемы
|
||||||
|
% \begin{itemize}
|
||||||
|
% \item Не все числа имеют представление.
|
||||||
|
% \item Преобразование в целые: $63,0/9,0 \to 7$, $0,63/0,09 \to 6$.
|
||||||
|
% \item Многие числа нельзя ввести или вывести точно: $0,2 \to 0,200000000003$.
|
||||||
|
% \item Порядок вычисления может влиять на результат и его точность: не выполняются законы ассоциативности и дистрибутивности.
|
||||||
|
% \item Проблемы сравнения: $x == y$.
|
||||||
|
% \end{itemize}
|
||||||
|
% \end{frame}
|
||||||
|
% \note{
|
||||||
|
|
||||||
|
% }
|
||||||
|
|
||||||
\begin{frame}
|
\begin{frame}
|
||||||
\frametitle{Типы, преобразование типов}
|
\frametitle{Типы, преобразование типов}
|
||||||
таблица из методички «Основные типы данных в языке Java»
|
таблица из методички «Основные типы данных в языке Java»
|
||||||
\end{frame}
|
\end{frame}
|
||||||
\note{
|
\note{
|
||||||
Что ещё важного мы видив в этой таблице? шесть из восьми примитивных типов могут иметь как положительные, так и отрицательные значения
|
Казалось бы, это было так давно, но вернёмся к нашей таблице с примитивными типами данных. Что ещё важного мы видив в этой таблице? шесть из восьми примитивных типов могут иметь как положительные, так и отрицательные значения они называются одним словом «знаковые» типы.
|
||||||
}
|
}
|
||||||
|
|
||||||
\begin{frame}
|
\begin{frame}
|
||||||
|
|
Loading…
Reference in New Issue