diff --git a/02-основные-типы-данных-выражения/README.md b/02-основные-типы-данных-выражения/README.md index 955e606..5a65da1 100644 --- a/02-основные-типы-данных-выражения/README.md +++ b/02-основные-типы-данных-выражения/README.md @@ -5,9 +5,9 @@ - [2.2. Литералы](#2-2-литералы) - [2.2.1. Логические литералы](#2-2-1-логические-литералы) - [2.2.2. Целые литералы](#2-2-2-целые-литералы) - - [2.2.3. Литералы с плавающей запятой]() - - [2.2.4. Знаковые литералы]() - - [2.2.5. Строковые литералы]() + - [2.2.3. Литералы с плавающей запятой](#2-2-3-литералы-с-плавающей-запятой) + - [2.2.4. Знаковые литералы](#2-2-4-знаковые-литералы) + - [2.2.5. Строковые литералы](#2-2-5-строковые-литералы) - [2.2.5.1. Строковые литералы: WYSIWYG, с разделителями, строки токенов и импортированные]() - [2.2.5.2. Тип строкового литерала]() - [2.2.6. Литералы массивов и ассоциативных массивов]() @@ -190,7 +190,79 @@ auto targetSalary = 15_000_000; [В начало ⮍](#2-2-2-целые-литералы) [Наверх ⮍](#2-основные-типы-данных-выражения) +### 2.2.3. Литералы с плавающей запятой + +Литералы с плавающей запятой могут быть десятичными и шестнадцатеричными. Десятичные литералы с плавающей запятой легко определить по аналогии с только что определенными десятичными целыми числами: десятичный литерал с плавающей запятой состоит из десятичного литерала, который также может содержать точку[^5] в любой позиции, за ней могут следовать показатель степени (характеристика) и суффикс. Показатель степени[^6] – это то, что обозначается как `e`, `E`, `e+`, `E+`, `e-` или `E-`, после чего следует целый десятичный литерал без знака[^7]. В качестве суффикса может выступать `f`, `F` или `L`. Разумеется, хотя бы что-то одно из `e/E` и `f/F` должно присутствовать, иначе если в числе нет точки, вместо числа с плавающей запятой получим целое. Суффикс `f/F` заставляет компилятор определить тип литерала как `float`, а суффикс `L` – как `real`. Иначе литералу будет присвоен тип `double`. + +Может показаться, что шестнадцатеричные константы с плавающей запятой – вещь странноватая. Однако, как показывает практика, они очень удобны, если нужно записать число очень *точно*. Внутреннее представление чисел с плавающей запятой характеризуется тем, что числа хранятся в двоичном виде, поэтому запись вещественного числа в десятичном виде повлечет преобразования, невозможные без округлений, поскольку 10 – не степень 2. Шестнадцатеричная форма записи, напротив, позволяет записать число с плавающей запятой точно так, как оно будет представлено. Полный курс по представлению чисел с плавающей запятой выходит за рамки этой книги; отметим лишь, что все реализации D гарантированно используют формат IEEE 754, полную информацию о котором можно найти в Сети (сделайте запрос «формат чисел с плавающей запятой IEEE 754»). + +Шестнадцатеричный литерал с плавающей запятой состоит из префикса `0x` или `0X`, за которым следует строка шестнадцатеричных цифр, содержащая точку в любой позиции. Затем идет обязательный показатель степени[^8], который начинается с `p`, `P`, `p+`, `P+`, `p-` или `P-` и заканчивается десятичными (не шестнадцатеричными!) цифрами. Только так называемая мантисса – дробная часть перед показателем степени – выражается шестнадцатеричным числом; сам показатель степени – целое десятичное число. Показатель степени шестнадцатеричной константы с плавающей запятой означает степень 2 (а не 10, как в случае с десятичным представлением). Завершается литерал необязательным суффиксом `f`, `F` или `L`[^9]. Рассмотрим несколько подходящих примеров: + +```d +auto + a = 1.0, // a имеет тип double + b = .345E2f, // b = 34.5 имеет тип float + c = 10f, // c имеет тип float из-за суффикса + d = 10., // d имеет тип double + e = 0x1.fffffffffffffp1023, // наибольшее возможное значение типа double + f = 0XFp1F; // f = 30.0, тип float +``` + +Рисунок 2.2 без лишних слов описывает литералы с плавающей запятой языка D. Правила интерпретации автомата те же, что и для автомата, иллюстрирующего распознавание целых литералов: переход выполняется по мере чтения знаков литерала с целью прочитать как можно больше. Представление в виде автомата проясняет несколько фактов, которые было бы утомительно описывать, не используя формальный аппарат. Например, `0x.p1` и `0xp1` – вполне приемлемые, хотя и странные формы записи нуля, а конструкции типа `0e1`, `.e1` и `0x0.0` запрещены. + +![image-2-2](images/image-2-2.png) + +***Рис. 2.2.*** *Распознавание литералов с плавающей запятой* + +[В начало ⮍](#2-2-3-литералы-с-плавающей-запятой) [Наверх ⮍](#2-основные-типы-данных-выражения) + +### 2.2.4. Знаковые литералы + +Знаковый литерал – это один знак, заключенный в одиночные кавычки, например `'a'`. Если в качестве знака выступают сами кавычки, их нужно экранировать с помощью обратной косой черты: `'\''`. На самом деле в D, как и в других языках, определены несколько разных escape-последовательностей[^10] (см. табл. 2.3). В дополнение к стандартному набору управляющих непечатаемых символов D предоставляет следующие возможности записать знаки Юникода: `'\u03C9'` (знаки `\u`, за которыми следуют ровно 4 шестнадцатеричные цифры), `'\U0000211C'` (знаки `\U`, за которыми следуют ровно 8 шестнадцатеричных цифр) и `'\©'` (имя, окруженное знаками `\&` и `;`). Первый из этих примеров – знак `ω` в Юникоде, второй – красивая письменная `ℬ`, а последний – грозный знак `©`. Если вам нужен полный список знаков, которые можно отобразить, поищите в Интернете информацию о таблице знаков Юникода. + +*Таблица 2.3. Экранирующие последовательности в D* + +|Escape-последовательность|Тип|Описание| +|-|-|-| +|`\"`|`char`|Двойная кавычка (если двусмысленно)| +|`\\`|`char`|Обратная косая черта| +|`\a`|`char`|Звуковой сигнал (Bell, ASCII 7)| +|`\b`|`char`|Backspace (ASCII 8)| +|`\f`|`char`|Смена страницы (ASCII 12)| +|`\n`|`char`|Перевод строки (ASCII 10)| +|`\r`|`char`|Возврат каретки (ASCII 13)| +|`\t`|`char`|Табуляция (ASCII 9)| +|`\v`|`char`|Вертикальная табуляция (ASCII 11)| +|`\<1–3 восьмеричные цифры>`|`char`|Знак UTF-8 в восьмеричном представлении (не больше 3778)| +|`\x<2 шестнадцатеричные цифры>`|`char`|Знак UTF-8 в шестнадцатеричном представлении| +|`\u<4 шестнадцатеричные цифры>`|`wchar`|Знак UTF-16 в шестнадцатеричном представлении| +|`\U<8 шестнадцатеричных цифр>`|`dchar`|Знак UTF-32 в шестнадцатеричном представлении| +|`\&<имя знака>;`|`dchar`|Имя знака Юникод| + +[В начало ⮍](#2-2-4-знаковые-литералы) [Наверх ⮍](#2-основные-типы-данных-выражения) + +### 2.2.5. Строковые литералы + +Теперь, когда мы знаем, как представляются отдельные знаки, строковые литералы для нас пустяк. D прекрасно справляется с обработкой строк отчасти благодаря своим мощным средствам представления строковых литералов. Как и другие языки, работающие со строками, D различает строки, заключенные в кавычки (внутри которых можно размещать экранированные последовательности из табл. 2.3), и WYSIWYG-строки[^11] (которые компилятор распознает «вслепую», не пытаясь обнаружить и расшифровать никакие escape-последовательности). Стиль WYSIWYG очень удобен для представления строк, где иначе пришлось бы использовать множество экранированных знаков; два выдающихся примера – регулярные выражения и пути к файлам в системе Windows. Строки, заключенные в кавычки (quoted strings), – это последовательности знаков в двойных кавычках, `"как в этом примере"`. В таких строках все escape-последовательности из табл. 2.3 являются значимыми. Строки всех видов, расположенные подряд, автоматически подвергаются конкатенации: + +```d +auto crlf = "\r\n"; +auto a = "В этой строке есть \"двойные кавычки\", а также +перевод строки, даже два" "\n"; +``` + +Текст умышленно перенесен на новую строку после слова `также`: строковый литерал может содержать знак перевода строки (реальное начало новой строки в исходном коде, а не комбинацию `\n`), который будет сохранен именно в этом качестве. + +[В начало ⮍](#2-2-5-строковые-литералы) [Наверх ⮍](#2-основные-типы-данных-выражения) + [^1]: Впрочем, использование нелатинских букв является дурным тоном. – *Прим. науч. ред.* [^2]: С99 – обновленная спецификация C, в том числе добавляющая поддержку знаков Юникода. – *Прим. пер.* [^3]: Сам язык не поддерживает восьмеричные литералы, но поскольку они присутствуют в некоторых C-подобных языках, в стандартную библиотеку был добавлен соответствующий шаблон. Теперь запись `std.conv.octal!777` аналогична записи `0777` в C. – *Прим. науч. ред.* [^4]: Для тех, кто готов воспринимать теорию: автоматы на рис. 2.1 и 2.2 – это детерминированные конечные автоматы (ДКА). +[^5]: В России в качестве разделителя целой и дробной части чисел с плавающей запятой принята запятая (поэтому и говорят: «числа с плавающей *запятой*»), однако в англоговорящих странах для этого служит точка, поэтому в языках программирования (обычно основанных на английском – международном языке информатики) разделителем является точка. – *Прим. пер.* +[^6]: Показатель степени 10 по-английски – exponent, поэтому для его обозначения и используется буква `e`. – *Прим. пер.* +[^7]: Запись `Ep` означает «умножить на 10 в степени `p`», то есть `p` – это порядок. – *Прим. пер.* +[^8]: Степень по-английски – power, поэтому показатель степени 2 обозначается буквой `p`. – *Прим. пер.* +[^9]: Да, синтаксис странноватый, но D скопировал его из стандарта C99, чтобы не изобретать свою нотацию с собственными выкрутасами, которых все равно не избежать. +[^10]: Escape-последовательность (от англ. escape – избежать), экранирующая/управляющая последовательность – специальная комбинация знаков, отменяющая стандартную обработку компилятором следующих за ней знаков (они как бы «исключаются из рассмотрения»). – *Прим. пер.* +[^11]: WYSIWIG – акроним «What You See Is What You Get» (что видишь, то и получишь) – способ представления, при котором данные в процессе редактирования выглядят так же, как и в результате обработки каким-либо инструментом (компилятором, после отображения браузером и т. п.). – *Прим. пер.* diff --git a/02-основные-типы-данных-выражения/images/image-2-2.png b/02-основные-типы-данных-выражения/images/image-2-2.png new file mode 100644 index 0000000..45237cd Binary files /dev/null and b/02-основные-типы-данных-выражения/images/image-2-2.png differ