Что такое интерполяция в программировании
При выводе строк в консоли с помощью метода Console.WriteLine для встраивания значений в строку мы можем применять форматирование вместо конкатенации:
В строке «Имя: <0>Возраст: <1>» на место <0>и <1>затем будут вставляться в порядке следования значения переменныйх name и age
То же самое форматирование в строке мы можем сделать не только в методе Console.WriteLine, но и в любом месте программы с помощью метода string.Format :
Метод Format принимает строку с плейсхолдерами типа <0>, <1>и т.д., а также набор аргументов, которые вставляются на место данных плейсхолдеров. В итоге генерируется новая строка.
Спецификаторы форматирования
В методе Format могут использоваться различные спецификаторы и описатели, которые позволяют настроить вывод данных. Рассмотрим основные описатели. Все используемые форматы:
Задает формат денежной единицы, указывает количество десятичных разрядов после запятой
Целочисленный формат, указывает минимальное количество цифр
Экспоненциальное представление числа, указывает количество десятичных разрядов после запятой
Формат дробных чисел с фиксированной точкой, указывает количество десятичных разрядов после запятой
Задает более короткий из двух форматов: F или E
Также задает формат дробных чисел с фиксированной точкой, определяет количество разрядов после запятой
Задает отображения знака процентов рядом с число, указывает количество десятичных разрядов после запятой
Шестнадцатеричный формат числа
Форматирование валюты
Для форматирования валюты используется описатель «C»:
Число после описателя указывает, сколько чисел будет использоваться после разделителя между целой и дробной частью. При выводе также добавляется обозначение денежного знака для текущей культуры компьютера. В зависимости от локализации текущей операционной системы результат может различаться. Также обратите внимание на округление в первом примере.
Форматирование целых чисел
Для форматирования целочисленных значение применяется описатель «d»:
Число после описателя указывает, сколько цифр будет в числовом значении. Если в исходном числе цифр меньше, то к нему добавляются нули.
Форматирование дробных чисел
Для форматирования дробны чисел используется описатель F, число после которого указывает, сколько знаков будет использоваться после разделителя между целой и дробной частью. Если исходное число — целое, то к нему добавляются разделитель и нули.
Формат процентов
Описатель «P» задает отображение процентов. Используемый с ним числовой спецификатор указывает, сколько знаков будет после запятой:
Настраиваемые форматы
Используя знак #, можно настроить формат вывода. Например, нам надо вывести некоторое число в формате телефона +х (ххх)ххх-хх-хх:
Метод ToString
Метод ToString() не только получает строковое описание объекта, но и может осуществлять форматирование. Он поддерживает те же описатели, что используются в методе Format:
Интерполяция строк
Интерполяция строк призвана упростить форматирование строк. Так, перепишем пример с выводом значений переменных в строке:
Знак доллара перед строкой указывает, что будет осуществляться интерполяция строк. Внутри строки опять же используются плейсхолдеры <. >, только внутри фигурных скобок уже можно напрямую писать те выражения, которые мы хотим вывести.
Интерполяция по сути представляет более лаконичное форматирование. При этом внутри фигурных скобок мы можем указывать не только свойства, но и различные выражения языка C#:
Также внутри фигурных скобок можно выполнять более сложные выражения, например, вызывать методы:
Уже внутри строки можно применять форматирование. В этом случае мы можем применять все те же описатели, что и в методе Format . Например, выведем номер телефона в формате +x xxx-xxx-xx-xx:
Интерполяция строк
Интерполяция строк предоставляет собой удобный вариант синтаксиса для создания форматированных строк.
Добавление специального символа $ перед открывающей кавычкой строки позволяет включать переменные в фигурных скобках, например:
Структура такой строки выглядит следующим образом:
interpolationExpression — выражение, определяющее вывод;
alignment — вырывание вывода (знак, отрицательный — по левому краю) и минимальное число символов вывода;
formatString — строка форматирования вывода, поддерживаемая типом результата выражения.
Буквальный идентификатор
Символ @ определяет буквальный строковый литерал, указывающий, что строковый литерал следует интерпретировать буквально, за исключением случаев:
- escape-последовательность кавычек ( "" ) не интерпретируется буквально, а создается одна двойная кавычка;
- escape-последовательность фигурных скобок ( << и >> ) не интерпретируются буквально в случае буквальной интерполированной строки, а создается одна фигурная скобка.
Символ @ может также предшествовать элементу кода, который компилятор должен интерпретировать как идентификатор, а не ключевое слово C#.
Например: @if будет обрабатываться компилятором как идентификатор (имя переменной), а не ключевое слово (зарезервированный идентификатор для построения условного выражения).
Интерполяция данных: соединяем точки так, чтобы было красиво
Как построить график по n точкам? Самое простое — отметить их маркерами на координатной сетке. Однако для наглядности их хочется соединить, чтобы получить легко читаемую линию. Соединять точки проще всего отрезками прямых. Но график-ломаная читается довольно тяжело: взгляд цепляется за углы, а не скользит вдоль линии. Да и выглядят изломы не очень красиво. Получается, что кроме ломаных нужно уметь строить и кривые. Однако тут нужно быть осторожным, чтобы не получилось вот такого:
Немного матчасти
Восстановление промежуточных значений функции, которая в данном случае задана таблично в виде точек P1 .  Pn, называется интерполяцией. Есть множество способов интерполяции, но все они могут быть сведены к тому, что надо найти n – 1 функцию для расчёта промежуточных точек на соответствующих сегментах. При этом заданные точки обязательно должны быть вычислимы через соответствующие функции. На основе этого и может быть построен график: 
Функции fi могут быть самыми разными, но чаще всего используют полиномы некоторой степени. В этом случае итоговая интерполирующая функция (кусочно заданная на промежутках, ограниченных точками Pi) называется сплайном.
В разных инструментах для построения графиков — редакторах и библиотеках — задача «красивой интерполяции» решена по-разному. В конце статьи будет небольшой обзор существующих вариантов. Почему в конце? Чтобы после ряда приведённых выкладок и размышлений можно было поугадывать, кто из «серьёзных ребят» какие методы использует.
Ставим опыты
Самый простой пример — линейная интерполяция, в которой используются полиномы первой степени, а в итоге получается ломаная, соединяющая заданные точки.
Давайте добавим немного конкретики. Вот набор точек (взяты почти с потолка):
Результат линейной интерполяции этих точек выглядит так: 
Однако, как отмечалось выше, иногда хочется получить в итоге гладкую кривую.
Что есть гладкость? Бытовой ответ: отсутствие острых углов. Математический: непрерывность производных. При этом в математике гладкость имеет порядок, равный номеру последней непрерывной производной, и область, на которой эта непрерывность сохраняется. То есть, если функция имеет гладкость порядка 1 на отрезке [a; b], это означает, что на [a; b] она имеет непрерывную первую производную, а вот вторая производная уже терпит разрыв в каких-то точках.
У сплайна в контексте гладкости есть понятие дефекта. Дефект сплайна — это разность между его степенью и его гладкостью. Степень сплайна — это максимальная степень использованных в нём полиномов.
Важно отметить, что «опасными» точками у сплайна (в которых может нарушиться гладкость) являются как раз Pi, то есть точки сочленения сегментов, в которых происходит переход от одного полинома к другому. Все остальные точки «безопасны», ведь у полинома на области его определения нет проблем с непрерывностью производных.
Чтобы добиться гладкой интерполяции, нужно повысить степень полиномов и подобрать их коэффициенты так, чтобы в граничных точках сохранялась непрерывность производных.
Традиционно для решения такой задачи используют полиномы третьей степени и добиваются непрерывности первой и второй производной. То, что получается, называют кубическим сплайном дефекта 1. Вот как он выглядит для наших данных: 
Кривая, действительно, гладкая. Но если предположить, что это график некоторого процесса или явления, который нужно показать заинтересованному лицу, то такой метод, скорее всего, не подходит. Проблема в ложных экстремумах. Появились они из-за слишком сильного искривления, которое было призвано обеспечить гладкость интерполяционной функции. Но зрителю такое поведение совсем не кстати, ведь он оказывается обманут относительно пиковых значений функции. А ради наглядной визуализации этих значений, собственно, всё и затевалось.
Так что надо искать другие решения.
Другое традиционное решение, кроме кубических сплайнов дефекта 1 — полиномы Лагранжа. Это полиномы степени n – 1, принимающие заданные значения в заданных точках. То есть членения на сегменты здесь не происходит, вся последовательность описывается одним полиномом.
Но вот что получается: 
Гладкость, конечно, присутствует, но наглядность пострадала так сильно, что… пожалуй, стоит поискать другие методы. На некоторых наборах данных результат выходит нормальный, но в общем случае ошибка относительно линейной интерполяции (и, соответственно, ложные экстремумы) может получаться слишком большой — из-за того, что тут всего один полином на все сегменты.
В компьютерной графике очень широко применяются кривые Безье, представленные полиномами k-й степени.
Они не являются интерполирующими, так как из k + 1 точек, участвующих в построении, итоговая кривая проходит лишь через первую и последнюю. Остальные k – 1 точек играют роль своего рода «гравитационных центров», притягивающих к себе кривую.
Вот пример кубической кривой Безье:
Как это можно использовать для интерполяции? На основе этих кривых тоже можно построить сплайн. То есть на каждом сегменте сплайна будет своя кривая Безье k-й степени (кстати, k = 1 даёт линейную интерполяцию). И вопрос только в том, какое k взять и как найти k – 1 промежуточную точку.
Здесь бесконечно много вариантов (поскольку k ничем не ограничено), однако мы рассмотрим классический: k = 3.
Чтобы итоговая кривая была гладкой, нужно добиться дефекта 1 для составляемого сплайна, то есть сохранения непрерывности первой и второй производных в точках сочленения сегментов (Pi), как это делается в классическом варианте кубического сплайна.
Решение этой задачи подробно (с исходным кодом) рассмотрено здесь.
Вот что получится на нашем тестовом наборе: 
Стало лучше: ложные экстремумы всё ещё есть, но хотя бы не так сильно отличаются от реальных.
Думаем и экспериментируем
Можно попробовать ослабить условие гладкости: потребовать дефект 2, а не 1, то есть сохранить непрерывность одной только первой производной.
Достаточное условие достижения дефекта 2 в том, что промежуточные контрольные точки кубической кривой Безье, смежные с заданной точкой интерполируемой последовательности, лежат с этой точкой на одной прямой и на одинаковом расстоянии: 
В качестве прямых, на которых лежат точки Ci – 1 (2) , Pi и Ci (1) , целесообразно взять касательные к графику интерполируемой функции в точках Pi. Это гарантирует отсутствие ложных экстремумов, так как кривая Безье оказывается ограниченной ломаной, построенной на её контрольных точках (если эта ломаная не имеет самопересечений).
Методом проб и ошибок эвристика для расчёта расстояния от точки интерполируемой последовательности до промежуточной контрольной получилась такой:
Первая и последняя промежуточные контрольные точки равны первой и последней точке графика соответственно (точки C1 (1) и Cn – 1 (2) совпадают с точками P1 и Pn соответственно).
В этом случае получается вот такая кривая: 
Как видно, ложных экстремумов уже нет. Однако если сравнивать с линейной интерполяцией, местами ошибка очень большая. Можно сделать её ещё меньше, но тут в ход пойдут ещё более хитрые эвристики.
К текущему варианту мы пришли, уменьшив гладкость на один порядок. Можно сделать это ещё раз: пусть сплайн будет иметь дефект 3. По факту, тем самым формально функция не будет гладкой вообще: даже первая производная может терпеть разрывы. Но если рвать её аккуратно, визуально ничего страшного не произойдёт.
Отказываемся от требования равенства расстояний от точки Pi до точек Ci – 1 (2) и Ci (1) , но при этом сохраняем их все лежащими на одной прямой: 
Эвристика для вычисления расстояний будет такой:
Результат получается такой: 
В результате на шестом сегменте ошибка уменьшилась, а на седьмом — увеличилась: кривизна у Безье на нём оказалась больше, чем хотелось бы. Исправить ситуацию можно, принудительно уменьшив кривизну и тем самым «прижав» Безье ближе к отрезку прямой, которая соединяет граничные точки сегмента. Для этого используется следующая эвристика:
Результат следующий: 
На этом было принято решение признать цель достигнутой.
Может быть, кому-то пригодится код.
А как люди-то делают?
Обещанный обзор. Конечно, перед решением задачи мы посмотрели, кто чем может похвастаться, а уже потом начали разбираться, как сделать самим и по возможности лучше. Но вот как только сделали, не без удовольствия ещё раз прошлись по доступным инструментам и сравнили их результаты с плодами наших экспериментов. Итак, поехали.
MS Excel

Это очень похоже на рассмотренный выше сплайн дефекта 1, основанный на кривых Безье. Правда, в отличие от него в чистом виде, тут всего два ложных экстремума — первый и второй сегменты (у нас было четыре). Видимо, к классическому поиску промежуточных контрольных точек тут добавляются ещё какие-то эвристики. Но ото всех ложных экстремумов они не спасли.
LibreOffice Calc

В настройках это названо кубическим сплайном. Очевидно, он тоже основан на Безье, и вот тут уже точная копия нашего результата: все четыре ложных экстремума на месте.
Есть там ещё один тип интерполяции, который мы тут не рассматривали: B-сплайн. Но для нашей задачи он явно не подходит, так как даёт вот такой результат 🙂 
Highcharts, одна из самых популярных JS-библиотек для построения диаграмм

Тут налицо «метод касательных» в варианте равенства расстояний от точки интерполируемой последовательности до промежуточных контрольных. Ложных экстремумов нет, зато есть сравнительно большая ошибка относительно линейной интерполяции (седьмой сегмент).
amCharts, ещё одна популярная JS-библиотека

Картина очень похожа на экселевскую, те же два ложных экстремума в тех же местах.
Coreplot, самая популярная библиотека построения графиков для iOS и OS X

Есть ложные экстремумы и видно, что используется сплайн дефекта 1 на основе Безье.
Библиотека открытая, так что можно посмотреть в код и убедиться в этом.
aChartEngine, вроде как самая популярная библиотека построения графиков для Android

Больше всего похоже на кривую Безье степени n – 1, хотя в самой библиотеке график называется «cubic line». Странно! Как бы то ни было, тут не только присутствуют ложные экстремумы, но и в принципе не выполняются условия интерполяции.
Name already in use
less-guidebook-for-beginners / chapter_3 / variable-interpolation.md
- Go to file T
- Go to line L
- Copy path
- Copy permalink
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
Если вы раньше работали с PHP или Ruby, то должны были хотя бы раз использовать интерполяцию переменных. Интерполяция переменных — это получение значения одной переменной в зависимости от другой или других переменных.
В Less есть конструкции типа @<> , которые технически похожи на интерполяцию переменных. Такие конструкции могут быть использованы в селекторах, переменных и строках. Далее будут рассмотрены все популярные и почти не применяемые варианты использования интерполяции переменных.
Я не зря вынес эту интересную тему в отдельный раздел, так как с помощью интерполяции переменных можно творить чудеса и делать ваш проект или библиотеку максимально настраиваемыми.
Интерполяция переменных в строках
Начинать нужно с основ, так как, если есть желание овладеть технологией в полной мере, то именно основы дадут понимание того, как что-то работает или почему это что-то не работает.
Основами интерполяции переменных являются строки. Именно в них чаще всего может понадобиться подставить значение одной переменной и получить необходимое значение другой переменной, к которой относится эта строка. Это позволяет настраивать пути до изображений, шрифтов, или библиотек не используя поиск по всему проекту для их редактирования.
Интерполяция переменных в строках, как это ни странно, происходит в строках тогда, когда название переменной оборачивается в специальную конструкцию, которая выглядит следующим образом:
Конструкции @
В этом примере мы подробно разберём то, как происходит интерполяция переменных. Инициализируем несколько переменных и поместим их в начале файла _styles.less так, как это было описано в начале главы:
Чтобы воспользоваться шрифтом FontAwesome, в проекте необходимо использовать директиву @font-face . Ради экономии места я не стал вставлять сюда весь код примера, он, как и любой код в примерах, будет доступен в архиве.
На выходе компилятора получим следующий код:
Обратите внимание, если поменять вызов переменной @
Интерполяция переменных в селекторах и свойствах
Иногда требуется делать код гибким вплоть до того, чтобы селекторы изменяли своё имя в зависимости от значения переменных. Наиболее вероятно, что такое поведение пригодится в библиотеках или фреймворках, в которых разработчики хотят разрешить изменять префикс классов их детища.
Интерполяция переменных в селекторах по конструкции полностью повторяет таковую в строках:
Компилятор сам позаботится о формировании имени класса из двух переменных, инициализированных ранее:
Никто не запрещает использовать интерполяцию и в рамках свойств. Конструкция вида:
будет компилироваться в:
Интерполяция переменных внутри переменных
Важно понимать, что хороший код должен быть адаптируемым. То есть имена селекторов и значения свойств должны меняться в зависимости от контекста использования, если это требуется разработчику.
С помощью примесей, которые будут рассматриваться позднее, можно писать адаптируемый и переиспользуемый код. Для этого в примесях используются значения, передаваемые как аргументы. В зависимости от передаваемых значений, можно формировать названия переменных, которые в последствии будут вызываться.
Так как примеси мы ещё не проходили, а интерполяцию переменных внутри переменных показать и объяснить нужно, то представим себе ситуацию, в которой у нас есть несколько переменных:
Разработчику нужно выбрать серый и красный цвет, но префикс переменных, в которых хранится искомое значение, ему не известен — он хранится в переменной @color-prefix .
Чтобы получить цвета, разработчику нужно построить переменную на основе уже известной ему переменной:
Обратите внимание на то, что здесь используется экранирование, так как конструкция внутри очень похожа на конструкцию переменной, но в то же время не являющаяся ей. Далее нужно обернуть конструкцию в @<> столько раз, сколько раз планируется собирать переменную из частей. Проще говоря, мы конструируем строку, а потом получаем значение переменной, имя которой совпадает с этой строкой.
Однако, ложкой дёгтя является то, что при такой интерполяции значение всегда приводится к строке. Это поведение стоит отнести к частному случаю, который также имеет своё решение, пусть и не самое элегантное.
Частый случай интерполяции переменных внутри переменных
В некоторых случаях появляется необходимость получить значение переменной, имя которой задано в другой переменной. Примером может служить примесь, которая выставляет отступы блока в зависимости от переданной в неё строки. Рассмотрим эту проблему более детально.
Допустим, разработчик опытным путем или на глаз определил, что все блоки на странице делятся на два типа: с маленьким и большим отступом. Здесь под отступом стоит понимать, как внутренний, так и внешний отступ. Для стандартизации кода эти размеры будут вынесены в переменные:
В будущем разработчик напишет примесь, но, так как сейчас я о примесях ещё ничего не говорил, вместо неё будем использовать переменную @size . В этой переменной будет содержаться имя размера блока, то есть small или large . Попробуем получить отступы для произвольного блока, используя описанный выше метод интерполяции переменных внутри переменных:
Этот код будет скомпилирован в CSS без ошибок и свойству margin будет присвоено значение 40px . Однако, в этой синтаксической конструкции скрывается немного чёрной магии. Понять проблему поможет простая операция сложения, которую необходимо провести с интерполяцией. Давайте попробуем сложить внешний и внутренний отступ.
Вот это поворот! Ошибка!
Не буду томить читателя своими догадками и анализом происходящего — Less не умеет складывать строки. Функция экранирования возвращает строку. Да, вот так вот просто — сложить строку со строкой или строку с числом в Less нельзя. По крайне мере, в версии 2.7.1 это сделать нельзя. Впрочем, эта возможность присутствует в Sass и Stylus.
Так как же решить возникшую проблему? — использовать интерполяцию переменных с помощью конструкции @@ . К сожалению, для этого придётся ввести дополнительную переменную для каждого слагаемого.
После компиляции свойству margin будет присвоено значение 60px . Это происходит вследствие того, что в переменной @margin после интерполяции находится имя переменной margin-small . Точно такая же ситуация со значением в переменной @padding . При вызове переменной с помощью конструкции @@ на её место подставляется значение переменной, имя которой указано в строке.