Log10 — Функция Delphi

Содержание

Математические функции в Delphi

Занимаясь программированием, невозможно обойтись без использования математических функций. Большинство алгоритмических задач, вычисления требуют умения пользоваться ими. Конечно, некоторые из этих функций можно заменить какими-то наборами операторов, но такие решения всегда будут громоздкими, содержать дополнительные условия и выглядеть как изобретенный велосипед. Гораздо проще посвятить немного времени изучению готовых функций и разобраться в их использовании.

Для работы с этими функциями, в разделе описания uses нужно указать математическую библиотеку Math:

В таблице приведены наиболее часто используемые функции.

Логирование в Delphi

Логирование (logging) — это ведение записей(как правило сохранение в файл) в хронологическом порядке.

Ведение логов зачастую очень удобная, облегчающая жизнь разработчику, штука, а для больших серьёзных проектов это вообще неотъемлемая вещь.

Логирование помогает как на этапе отладки, так и на этапе внедрения, например я прицеплял утилиту к проектам, которая отправляла файл лога куда мне удобно(сайт, мыло, сервер), таким образом избегал процесса вымогательства у пользователя лог-файла.

Я использую логирование почти во всех своих проектах от средне до велика.

В этой статье я рассмотрю свою реализацию модуля ведения логов, которым пользуюсь и время от времени грейжу его.

Данный модуль можно так же применять в многопоточных приложениях.

Былина

За свою практику я переписал не мало разновидностей процессов логирования и каждый раз меня чутка тревожило ощущение, что «что-то тут осталось не таким удобным как мне хотелось бы» и от этого постоянно что-то дописывал/переписывал.

Так я пришёл от модуля, содержащего глобальные переменные — параметры лога и глобальную функцию типа WriteToLog(aMsg: string): boolean, к модулю с классом — менеджером логирования и методами записи на WinApi. Время дало мне возможность, так сказать, выбрать самый удобный вариант.

Во время улучшения менеджера логирования я встречал одну интересную реализацию в плане процесса записи:

  • единое открытие файла на всё время работы приложения;
  • запись по таймеру накопившейся очереди сообщений.

При этом для работы с файлом использовался какой-нить стрим, зачастую TFileStream. Но при таких раскладах у нас есть довольно большой риск «просеять» в логе сообщение именно про ту ошибку, которая и привела к краху проги из-за которой не дописался лог…

Последнее важное изменение я внёс когда обнаружил, что мой менеджер пишет строку поверх другой строки при могопоточном использовании, хоть и допускал возможность такого использования.

Реализация

Я реализовал следующие элементы удобства:

  • единый класс логирования для всего приложения посредством шаблона Singleton;
  • типы сообщений (информация, предупреждение, ошибка);
  • уровень приоритета сообщений (максимальный, информативный, отладочный);
  • событийные типы как для объектных методов так и для обычных процедур;
  • настройка менеджера через свойства;
  • формирование заголовка из текущей даты и типа сообщения.

Код всего модуля uLogManager отображён в следующем листинге ( Delphi 2007 ):

Функции Delphi

Стандартные функции Delphi:

Для проведения всевозможных математических вычислений и многочисленных преобразований язык программирования Delphi содержит библиотеки стандартных процедур и функций. Давайте подробнее рассмотрим стандартные функции Delphi.

Между значением и именем функции существует зависимость. Поэтому всякая функция может быть представлена как операнд некоторого выражения (к примеру, в инструкции присваивания). Для возведения числа в n-ую степень достаточно записать

откуда ln — функция, вычисляющая натуральный логарифм числа exp(x), exp — функция, вычисляющая экспоненту в степени x, x — число, n-ую степень которого надо найти, а n — степень числа x. Каждая функция обладает следующими характеристиками: тип значений, тип параметров.

Должно существовать соответствие между типом переменной (ей присваивается определенное значение функции) и типом функции. И в то же время необходимо соответствие между типом фактического параметра данной функции (фактический параметр — это параметр, который указывается при обращении к функции) и типом формального параметра. В противном случае компилятором выводится сообщение об ошибке.

Математические функции Delphi:

Библиотеки языка Delphi включаются в себя и множество математических функций:

Величину угла при использовании тригонометрических функций необходимо выражать в радианах. Чтобы преобразовать угол из градусов в радианы, используйте следующую формулу:

где a выражает угол в градусах; 3.1415926 означает число pi. На месте константы 3.1415926 с дробной частью для достижения большей точности чаще всего пользуются стандартной именованной константой pi. Тогда выражения для угла в пересчете в радианы будет выглядеть следующим образом:

Функции преобразования Delphi:

Наиболее частое использование функций преобразования связано с инструкциями, которые обеспечивают ввод/вывод какой-либо информации. Например, для вывода значения переменной c типом real в поле вывода диалогового окна (компонент Label), нужно провести преобразование числа в строку символов, которая собственно изображает данное число. Это можно достичь, применяя функцию FloatToStr, которая заменяет значение выражения (оно указано как параметр функции) его строковым представлением.

Пример.

В приведенном примере значение переменной m будете выведено в поле Label. В таблице ниже Вам будут представлены основные функции преобразования Delphi:

Применение функций Delphi:

В любом выражении функция используется как операнд. В качестве ее параметра можно выбрать переменную, константу, выражение определенного типа данных.

Примеры.

Структура функции Delphi

Как организована инструкция функции в языке Delphi? В любом языке программирования на первом этапе описания функции указывается ее заголовок. Далее за заголовком программист описывает раздел объявления констант const (если таковы имеются), затем занимается описанием раздела объявления типов type, далее следует раздел объявления переменных var и, наконец, раздел инструкций.

В приведенном примере в заголовке функции вначале указывается зарезервированное слово function, а следом идет имя функции. Далее в скобках программист перечисляет список параметров, и вслед за ним, используя символ «:», указывает тип значения функции. В конце каждого заголовка стоит символ «;». После заголовка следуют раздел констант, раздел типов, раздел переменных. Внутри раздела инструкций кроме констант и переменных, описанных соответственно в разделах const и var, может находится переменная result.

Когда инструкции функции завершат свое выполнение, значению переменной result присваивается значение функции. Таким образом, среди всех инструкций функций необходимое присутствие инструкции, которая бы присваивала переменной result окончательное значение функции. Обычно подобная инструкция есть последняя исполняемая инструкция функции. Представим пример функции FuntToKg, преобразующей фунты в килограммы.

LOG10 (функция LOG10)

В этой статье описаны синтаксис формулы и использование функции LOG10 в Microsoft Excel.

Описание

Возвращает десятичный логарифм числа.

Синтаксис

Аргументы функции LOG10 описаны ниже.

Число Обязательный. Положительное вещественное число, для которого вычисляется десятичный логарифм.

Пример

Скопируйте образец данных из следующей таблицы и вставьте их в ячейку A1 нового листа Excel. Чтобы отобразить результаты формул, выделите их и нажмите клавишу F2, а затем — клавишу ВВОД. При необходимости измените ширину столбцов, чтобы видеть все данные.

Десятичный логарифм числа 86. Результат (1,9345) — степень, в которую необходимо возвести основание 10, чтобы получить число 86.

Десятичный логарифм числа 10. Это степень, в которую необходимо возвести основание 10, чтобы получить число 10.

Десятичный логарифм числа (1E+5). Это степень, в которую необходимо возвести основание 10, чтобы получить число 100 000 (1E+5).

Десятичный логарифм числа 10^5. Совпадает с описанным выше; 1E+5 = 100 000.

Вычислить логарифм

Delphi , Синтаксис , Математика

Статья Вычислить логарифм раздела Синтаксис Математика может быть полезна для разработчиков на Delphi и FreePascal.

Комментарии и вопросы

Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.

Парсинг от А до Я

Блог о программировании парсеров и web-автоматизации

Поиск по блогу

четверг, 8 июля 2010 г.

Delphi: отладка, запись в лог

Давненько не писала про Delphi, а ведь именно в Delphi провожу большую часть дня :) Итак, сегодня расскажу о том, как я пишу логи.

Запись в лог я использую во всех более-менее серьезных проектах. Логирование помогает и на этапе отладки, и на этапе внедрения (иногда проще попросить прислать лог, чем со слов понять, в чем проблема). Давно уже использую для этих целей маленькую и удобную библиотечку uLog . Все, что от вас потребуется, это добавить ее в uses. Ну и по желанию некоторые настройки. Но даже уже без всяких настроек вы можете писать в лог с помощью процедуры sLog. Пример:

Первый входной параметр — куда писать, второй — что писать. Если путь прописан не полностью — идет обращение к текущей директории проекта. Если файл не существует — он будет создан автоматически. В логе строчки появляются снабженные временем записи в лог. Пример части лога:
(в квадратных скобках после времени — миллисекунды)

Немного о настройках. Первое, что можно настраивать, — это файл по умолчанию, в который будет писаться лог. Для этого обращаемся к uLog.LogFileName .
Пример:

После установки LogFileName лог будет писаться в указанный файл, если первый входной параметр у sLog не будет задан:

Еще один параметр — EnableMessages . Он отвечает за то, будут ли появляться сообщения об ошибке в этой библиотеке (например, когда файл лога не указан и не задан по умолчанию).

И, наконец, самый замечательный параметр. Он передается в sLog третьим. Это «уровень логирования», LogLevel .

Вы сами проставляете этот уровень в зависимости от того, что за информацию пишете в лог. Градация, например, может быть такой:

  1. мегаважный
  2. информационный (запустился, . )
  3. отладочный

Уровней может быть больше, сколько угодно. При приведенном в предыдущем абзаце варианте вы на этапе разработки используете LogLevel := 3, а когда устанавливаете продукт клиенту, ставите LogLevel 1 или 2. LogLevel удобно задавать в ini-файле и считывать при запуске приложения. Если вдруг у клиента внезапно начнутся какие-то сбои — под вашим руководством он сможет поменять уровень логирования на 3 и прислать вам файл с отладочной информацией, которая поможет вам выяснить причину сбоев.

Листинг этой чудесной библиотечки:

Добавлю ссылку на класс, который написал Егор. С помощью класса можно посмотреть дамп любой области памяти и актуальный стекфлоу. Спасибо ему большое!
___

Чтобы быть в курсе обновлений блога, можно подписаться на RSS.

Журналирование или логирование в Delphi XE3

Автор: Alex. Опубликовано в Программирование 25 Январь 2014 . просмотров: 30378

Передо мной возник вопрос, как логировать то, что происходит в программе в Delphi XE3. Причём мне нужно отписывать происходящие события не только в файл, но и в базу данных. Кроме того я хочу отписывать сообщения из двух приложений в один файл параллельно, т.е. из разных процессов. Поскольку за Delphi я не садился с далёкого 2000-го года, мне пришлось закатать рукава и заняться поисками, что появилось с тех давних времён.

Журналирование с помощью CodeSite

Изобретать велосипед и писать, что-то с нуля можно, но не очень хочется. Поэтому первое, что я посмотрел, это, а что есть в Delphi XE3 из коробки. Оказалось, что в комплект входит инструмент под названием CodeSite Express, т.е. урезанная версия CodeSite. Покупать я ничего не собирался и начал разбираться с экспресс-версией.

Справка для CodeSite не встраивается в справку Delphi XE3, но её можно открыть из меню Пуск. Написана она сразу для вариантов Delphi и .Net.

Для начала нужно – это подключить юнит CodeSiteLogging, и можно пользоваться методами глобального объекта CodeSite. Например, записать сообщение в лог:

При выполнении вышеприведённого кода автоматически всплывает окошко программы CodeSite Live Viewer с нашим сообщением.

Кроме того есть ещё много перегруженных вариантов функции Send. Например, можно записать сразу весь объект в журнал:

После этого вы сможете просмотреть все свойства объекта в момент записи в окне CodeSite Live Viewer на панели Inspector Pane, чтобы её открыть, нажмите на F11.

Режим работы CodeSite в которой вы сразу видите результат, это так называемый Live Logging. Теперь разберёмся с тем, как записывать журнал в файл, чтобы позже можно было анализировать его. Это делается так:

После выполнения этого кода окно CodeSite Live Viewer появляться не будет, зато в папке с исполняемым файлом создастся файл Log.csl, в котором будут содержаться все наши сообщения. Чтобы посмотреть этот файл просто откройте его в программе CodeSite Live Viewer.

Посмотрим, куда ещё можно записывать сообщения? Открываем справку по объекту TCodeSiteDestination и видим, что все другие варианты кроме Live Logging и File Logging – доступны только в полной версии инструмента. Кроме того, упоминания о записи сообщений в базу данных нет вообще (ни в платной ни в бесплатной версиях). Также есть ещё один минус в этом инструменте — вы не можете посмотреть файл журнала прямо на компьютере пользователя, если у вас нет программы для просмотра журнала CodeSite Live Viewer. Что ж буду искать дальше.

Журналирование с помощью log4delphi или log4d

Закончив с CodeSite я посмотрел в сторону компонентов от сторонних разработчиков. Я посмотрел несколько компонентов для логирования на сайте Torry’s Delphi, но мне ничего не приглянулось. И тогда я решил поискать наудачу. Программируя на Java и C# я пользовался для логирования библиотеками jog4j и log4net, соответственно. Оба решения активно разрабатываются и поддерживаются сообществом разработчиков под эгидой Apache Software Foundation. Кроме того у них есть решение для PHP — log4php и для C++ — log4cxx. Почему же они забыли про Delphi?

Здесь нужно пару слов сказать про систему логирования от Apache. Библиотеки log4… обладают широчайшими возможностями, они бесплатны, документированы и имеют открытые исходные коды. Журналы можно записывать в файл, в базу данных, в консоль (если у вас консольное приложение), отправлять сообщения командой netsend (для Windows) или на SMTP-сервер. Кроме того можно использовать фильтры и шаблоны сообщений.

Немного поискав в Интернете выяснилось, что есть две параллельные разработки log4delphi и log4d. Когда я начал скачивать исходники и бинарники библиотеки log4delphi (http://sourceforge.net/projects/log4delphi/files/log4delphi/), выяснилось, что последнее обновление библиотеки было 16.11.2010г. Для библиотеки log4d ещё более худшая ситуация: последние изменения файлов в архиве датируются от 11.06.2007, хотя последнее обновление архива стоит 29.04.2013. Ну, если они старые, это не значит, что плохие. Будем проверять.

Журналирование с помощью log4delphi

Первым делом посмотрим библиотеку log4delphi, т.к. она новее. Здесь есть файлы проектов для Delphi 6 и Delphi 7. Я же использую Delphi XE3, поэтому сначала я попытался открыть и откомпилировать проекты log4delphi_D7_STD.dpk и log4delphi_D7_PROF.dpk. При открытии этих файлов Delphi XE3 поломала их, поэтому проекты не скомпилировались из-за ошибки. Тогда я сделал новую bpl-библиотеку (меню New Project -> Package), добавил в проект все pas файлы (в том числе и в папке util) и после этого всё прекрасно скомпилировалось.

Теперь давайте разберёмся, что может и чего не может эта библиотека. Сразу начну с ложки дёгтя: библиотека log4delphi не поддерживает загрузку конфигурации из xml файла. Конфигурацию можно загружать из ini-файла или настраивать программно. Запись в базу данных происходит сразу, без буфферизации, плюс в SQL-запросе должны быть определённые параметры, а это неудобно. Кроме того не поддерживается запись сообщений в файл журнала из разных процессов (только монопольное владение файлом) и мало регулярных выражений для шаблонов. Всё это выяснилось при анализе исходного кода.

Но может быть кому-нибудь эта библиотека понравится. Здесь поддерживается запись сообщений в базу данных (посредством BDE, SqlExpr, InterBase Express) и в файл. Есть возможности формирования лога в виде обычного текстового файла, HTML-документа, XML-файла.

Журналирование с помощью log4d

Теперь посмотрим библиотеку log4d. Собственно это даже и не библиотека, это просто несколько файлов, которые вы можете выборочно добавить в свой проект, что довольно удобно, или добавить их в bpl-библиотеку. Я создал bpl-библиотеку и добавил в неё все файлы с расширением .pas и .inc. После этого я откомпилировал её и получил 54 ошибки. Это и не удивительно. Ведь эта библиотека рассчитана на определённые версии Delphi, в число которых моя Delphi не входит: Delphi 4, 5, 6, 7, 2005, 2006. Пришлось поправить файл Defines.inc. Я прописал туда две версии XE2 и XE3 (аналогично можно добавить вашу версию Delphi):

Кроме того пришлось дополнить функцию TLogCustomLayout.Init:

И пришлось выкинуть из проекта файл Log4DNM.pas, т.к. компонентов NM… (а именно компонента TNMSMTP) теперь нет в Delphi. Это не страшно, т.к. есть юнит Log4DIndy.pas, который выполняет те же функции (отправляет сообщения на SMTP-сервер), только с помощью компонента TIdSMTP, который сразу поставляется вместе с Delphi XE3.

Также в юните Log4DXML.pas пришлось по-другому подключить библиотеку MSXML:

В этом же юните пришлось убрать два варианта функции _Set_documentLocator. После этого проект скомпилировался.

Теперь о возможностях этой библиотеки. Здесь нет возможности записи сообщений в базу данных и также не возможна запись сообщений в файл из разных процессов, зато есть вывод сообщений в дебаггер и есть отправка сообщений SMTP-серверу. Поддерживается загрузка конфигурации из XML-документа и из ini-файла. Есть возможности формирования обычного текстового файла и HTML-документа.

Не смотря на то, что в этой библиотеки нет записи в базу данных, эта библиотека мне понравилась больше. По своей внутренней структуре она ближе к log4j и log4net. Поэтому я решил остановиться на этой библиотеке и дописать те куски, которых мне не хватает.

В результате, после моих правок, библиотека log4d умеет записывать сообщений в базу данных посредством ADO-компонентов (юнит Log4DDB.pas) с возможностью буферизации (если кому то не нравится ADO, можете по аналогии дописать свой обработчик сообщений, используя желаемые компоненты), позволяет записывать сообщения в файл из разных процессов, причём допускаются разные привилегии. Также я добавил возможность подставлять в сообщения название приложения, имя текущего пользователя и имя компьютера, с помощью шаблона (класс TLogPatternLayout).

Версию библиотеки log4d с моими правками вы можете скачать здесь:

Дополненная версия библиотеки log4d. Оригинал библиотеки можно найти здесь: http://log4d.sourceforge.net/.

В версии от 25.01.2014 добавлена возможность записи сообщений в базу данных с помощью ADO-компонентов и добавлена возможность записи сообщений в один файл журнала из разных процессов.

В версии от 20.02.2014 добавлена модель блокировки файла журнала MinimalLock (минимальная блокировка, файл блокируется при каждой записи) и исправлена ошибка в функции RollOver.

В версии от 26.12.2014 сделана поддержка Delphi XE2.

В версии от 28.05.2015 добавлена поддержка Delphi XE4 — XE7. На версиях XE4 — XE6 работа кода не проверялась.

В версии от 26.08.2015 добавлена поддержка Delphi XE8.

В версии от 26.10.2015 добавлена поддержка Delphi 10 Seattle.

В версии от 03.03.2020 добавлены таймауты соединения и команды в юнит Log4DDB.pas. Там же добавлена обработка ошибок при работе с БД если не используются транзакции.

В версии от 26.08.2020 сделано сохранение трассировки стека в объект TLogEvent и убрано использование юнита System.IOUtils.

В версии от 29.08.2020 сделана поддержка Delphi 2007. Исправлена ошибка при считывании MinimalLock из файла конфигурации.

В версии от 05.07.2020 добавлена поддержка Delphi 10.1 Berlin/Delphi 10.2 Tokyo и добавлено свойство ConnectivityTestQuery в TLogADOAppender для проверки соединения.

В версии от 30.06.2020 исправлена работа в режиме MinimalLock, добавлена поддержка Delphi 10.3 Rio.

log4d Версия:от 30.06.2020
25.01.2014 42.75 KB 1522

Теперь пару слов о том, как работать с библиотекой. Для начала библиотеку нужно сконфигурировать. Например, загрузить конфигурацию их xml-файла:

А вот и пример файла конфигурации (здесь указано, что сообщения будут переданы в хранимую процедуру SaveLogMessage и будут сохранены в текстовый файл App.log):

Можно сконфигурировать библиотеку log4d программно:

После того как библиотека сконфигурирована, можно писать сообщения:

Файл лога получится в данном примере примерно такой:

Вы так же можете поиграться с фильтрами, например, записывать ошибки в один файл, а остальные сообщения не записывать вообще или записывать в другой файл и т.п. В общем, вам решать, что и как использовать для логирования. Желаю успехов.

Работа со строками в Delphi 10.3 Rio

Работа со строками в Delphi — это отдельная и очень обширная тема. Рассмотреть в одной статье все тонкости и особенности строк delphi представляет собой достаточно сложную задачу сравнимую, наверное, с написанием небольшой книги, просто по причине того, что в Delphi на сегодняшний день используются разные типы строк (ShortString, AnsiString, UnicodeString и прочие) и каждый тип для чего-то да нужен — для обратной совместимости, для COM BSTR, для разработки под мобильные платформы и так далее.

Вместе с этим, Delphi постоянно развивается, что-то добавляется, что-то улучшается и вот уже те инструменты работы со строками в Delphi, которые вызывали недоумение своим появлением, например, в Delphi 2009 в Delphi 10.3 Rio начинают играть другими красками. На написание этой статьи меня подтолкнула статья « What’s New » для Delphi 10.3 Rio, а именно то, что разработчики Delphi отдельным пунктом выделили, что давным давно существующий в Delphi класс TStringBuilder оптимизирован и даже обзавелся перегруженным методом ToString использование которого может увеличить производительность. Вот я и решил проверить — на сколько же выросла производительность TStringBuilder в Delphi по сравнению с тем, что было в далеком 2008 году, когда не было ни поддержки мобильных платформ, ни x64 с Linux.

Справка по TStringBuilder

TStringBuilder — это специализированный класс для работы со строками в Delphi (аналог класса StringBuilder в .NET Framework).

TStringBuilder поддерживает выполнение таких операций со строками как конкатенация (сложение), поиск, заменена и вставка подстрок. При этом, массив символов может быть запрошен по индексу или преобразован в строку для сравнения.

На массив символов можно ссылаться напрямую, используя свойство Chars. Свойство Length содержит текущую длину массива символов.

Работать с классом TStringBuilder в Delphi достаточно просто:

Обратить внимание стоит на то, что TStringBuilder работает с 0-индексированными (0-based) строками — первый символ имеет индекс 0, а не 1, как мы привыкли в Delphi. В остальном же, работа с TStringBuilder основана на использовании следующих методов:

Append — добавить подстроку к строке (конкатенация строк). Метод перегружен поэтому, Вы можете добавлять к строке числа, массивы символов и другие типы, например так:

Insert — вставить подстроку в строку с заданной позиции (метод также перегружен)

Replace — заменить подстроку (или символ) на другую строку (символ). Заменяет все вхождения подстрок.

CopyTo — копирование части строки в строку-приемник.

В Delphi 10.3 Rio TStringBuilder обзавелся также перегруженным методом ToString:

По сообщению разработчиков Delphi, ToString (True) даст лучшую производительность, если больше не ожидается никаких изменений для TStringBuilder, поскольку это уменьшает объем копируемых данных.

Со всеми методами TStringBuilder можно ознакомиться в справке Delphi.

Меня же больше интересует насколько TStringBuilder стал более производительным в части конкатенации строк по сравнению с обычной (привычной, классической) операцией сложения?

Вводные для теста производительности TStringBuilder

Итак, что у меня имеется для тестирования TStringBuilder:

Стационарный компьютер имеет следующие характеристики:

  • Процессор Intel Core i5 8400 (6-ти ядерный)
  • ОЗУ: 16 ГБ
  • ОС: Windows 10 x64

Смартфон LG Q7+ (Android 8.1.0)

Модель процессора MediaTek MT6750S
Частота процессора 1.5 ГГц
Кол-во ядер процессора 8
Оперативная память 3 ГБ

Проверять будем конкатенацию (сложение) строк Delphi в следующем порядке:

  1. Проверяем скорость сложения строк с использованием метода Append TStringBuilder
  2. Проверяем обычное сложение строк (Str1+Str2)
  3. Проверяем скорость сложения строк с использованием метода Append TStringBuilder и вывод строки обновленным методом ToString(True).

Все три проверки буду проводить на всех доступных устройствах.

Приложение для тестирование производительности TStringBuilder

Версия для ОС Windows

Внешний вид приложения для теста производительности TStringBuilder в Windows:

Каждую операцию сложения строк будем повторять по десять раз и результаты теста выводить в TStringGrid.

Код обработчика OnClick:

Результаты теста TStringBuilder в Windows

Тестирование сложение двух строк

  • Строка 1: edStr1
  • Строка 2: edStr2
  • Количество сложений: 30 000 000
# TStringBuilder Классика TStringBuilder.ToString(True)
1 234 483 165
2 249 527 163
3 197 482 155
4 206 495 157
5 186 503 155
6 185 503 162
7 188 499 155
8 188 519 155
9 187 478 155
10 208 537 154

Прибавление к строке одного символа

  • Строка 1: edStr1
  • Строка 2: a
  • Количество сложений: 30 000 000
# TStringBuilder Классика TStringBuilder.ToString(True)
1 149 314 124
2 149 318 128
3 137 332 207
4 122 312 123
5 121 311 123
6 146 312 173
7 130 327 124
8 122 315 124
9 122 317 123
10 122 312 123

Как можно видеть из представленных результатов TStringBuilder при сложении строк оказывается практически вдвое быстрее, чем обычная операция сложения, чего ранее за этим классом не наблюдалось при работе в Windows — ранее время, затрачиваемое на операцию сложения было практически одинаковым или, как в свое время проверял Marco Cantu — TStringBuilder оказывался намного медленнее.

Версия для ОС Android

Внешний вид приложения для тестирования TStringBuilder:

Исходный код программы тот же, что и в версии для Windows с одним лишь исключением — результаты теста будут выводиться в обычный Memo:

Результаты теста TStringBuilder на LG Q7+

Тестирование сложение двух строк

  • Строка 1: edStr1
  • Строка 2: edStr2
  • Количество сложений: 1 000 000
# TStringBuilder Классика TStringBuilder.ToString(True)
1 302 849 232
2 233 847 221
3 231 830 221
4 230 828 224
5 230 831 221
6 238 829 227
7 230 821 221
8 230 821 221
9 230 838 223
10 238 822 228

Прибавление к строке одного символа

  • Строка 1: edStr1
  • Строка 2: a
  • Количество сложений: 1 000 000
# TStringBuilder Классика TStringBuilder.ToString(True)
1 302 776 221
2 221 774 218
3 221 775 219
4 221 776 218
5 221 772 218
6 221 773 218
7 221 773 219
8 221 773 219
9 221 773 219
10 221 772 218

Опять же, как можно видеть по результатам тестирования, TStringBuilder ускоряет работу по сложению двух строк примерно в 2,5 раза, при этом, новый метод ToString(True) дает незначительное ускорение по сравнению с обычным ToString.

Резюмируем

На рисунке ниже представлено среднее время сложения двух строк в Windows.

  1. Синий столбик — сложение двух строк
  2. Оранжевый — прибавление к строке одного символа

То де самое, но уже для Android:

Представленные выше диаграммы наглядно демонстрируют рост производительности TStringBuilder при работе со строками в Delphi 10.3 Rio как в Windows, так и в Android. Между тем, новые метод TStringBuilder.ToStrng(True) дает незначительный прирост производительности по сравнению с ранее существующим методом ToString.

Таким образом, если в вашем приложении Delphi часто приходится иметь дело со строками, то, думаю, что имеет смысл обратит внимание на работу с TStringBuilder вне зависимости от того в какой операционной системе вы работаете.

Остается открытым вопрос о производительности TStringBuilder при работе в многопоточных приложениях, но это уже отдельная тема повышения производительности работы со строками в Delphi в принципе.

Исходники обоих тестовых приложений можно скачать со страницы:

Использование процедур и функций в Delphi

Скобки

Добавление скобок при вызове процедур и функций без параметров уже давно не является новинкой в Delphi, тем не менее, эта возможность мало известна. Эту возможность оценят по достоинству те программисты, которым приходится работать на двух языках (C++ и Delphi), так как им не нужно будет постоянно помнить о разнице в синтаксисе при вызове процедур и функций в разных языках. В Delphi оба варианта, приведенные ниже, считаются корректными.

Возможность перегрузки

Впервые концепция перегрузки процедур и функций была реализована в Delphi 4. Она позволяет иметь несколько различных процедур и функций с одинаковыми именами, но с разными списками параметров. Такие процедуры и функции должны быть описаны с применением директивы overload.

procedure Test (I: integer); overload;
procedure Test (S: string); overload;
procedure Test (D: double); overload;

При вызове процедуры Test, Delphi сама решит, какую из трех процедур необходимо выполнить, в зависимости от передаваемого ей параметра. Но нужно отметить, что это не самая безопасная возможность языка. Применение перегружаемых процедур и функций может стать неиссякаемым источником трудноуловимых ошибок в программе. Поэтому пользуйтесь этой возможностью осторожно.

Передача параметров

Pascal позволяет передавать параметры в функции и процедуры либо по значению, либо по ссылке. Передаваемый параметр может иметь любой встроенный или пользовательский тип либо являться открытым массивом. Параметр также может быть константой, если его значение в процедуре или функции не меняется.

Передача параметров по значению

Этот режим передачи параметров применяется по умолчанию. Если параметр передается по значению, создается локальная копия данной переменной, которая и предоставляется для обработки в процедуру или функцию. Посмотрите на следующий пример:

procedure Test(s: string);

При вызове указанной процедуры будет создана копия передаваемой ей в качестве параметра строки s, с которой и будет работать процедура Test. При этом все внесенные в строку изменения никак не отразятся на исходной переменной s.

Однако это не относится к объектам. Например, если в функцию передается переменная (а точнее экземпляр объекта) TStringList, то в данном случае произойдет передача по ссылке (даже если это не указано явно). Этот способ передачи является у большинства самым излюбленным, но в тоже время является и самым не практичным, т.к. для выполнения метода выделяется дополнительная память для создания точной копией передаваемой переменой. Для решения этой проблемы следует использовать один из способов описанных ниже.

Передача параметров по ссылке

Pascal позволяет также передавать параметры в функции или процедуры по ссылке — такие параметры называются параметрами-переменными. Передача параметра по ссылке означает, что функция или процедура сможет изменить полученные значения параметров. Для передачи параметров по ссылке используется ключевое слово var, помещаемое в список параметров вызываемой процедуры или функции.

procedure ChangeMe(var x: longint);
begin
x := 2; // Параметр х изменен вызванной процедурой
end;

Вместо создания копии переменной x, ключевое слово var требует передачи адреса самой переменной x, что позволяет процедуре непосредственно изменять ее значение.

Передача параметров констант

Если нет необходимости изменять передаваемые функции или процедуре данные, можно описать параметр как константу. Ключевое слово const не только защищает параметр от изменения, но и позволяет компилятору сгенерировать более оптимальный код передачи строк и записей. Вот пример объявления параметра-константы:

procedure Test(const s: string );

Передача открытых массивов

Открытый массив параметров позволяет передавать в функцию или процедуру различное количество параметров. В качестве параметров можно передать либо открытый массив элементов одинакового типа, либо массивы констант различного типа. В приведенном ниже примере объявляется функция, которой в качестве параметра должен передаваться открытый массив целых чисел.

function AddEmUp(A: array of integer): integer;

В открытом массиве можно передавать переменные, константы или выражения из констант.

Для получения информации о фактически передаваемом массиве параметров в функции или процедуре могут использоваться функции High, Low и SizeOf.

Object Pascal также поддерживает тип array of const, который позволяет передавать в одном массиве данные различных типов. Синтаксис объявления функций или процедур, использующих такой массив для получения параметров, следующий:

procedure WhatHaveIGot( A: array of const );

Вызвать объявленную выше функцию можно, например, с помощью такого оператора:

procedure WhatHaveIGot( [‘Text’, 10, 5.5, @WhatHaveIGot, 3.14, true, ‘c’] );

При передаче функции или процедуре массива констант все передаваемые параметры компилятор неявно конвертирует в тип TVarRec. Тип данных TVarRec объявлен в модуле System следующим образом:

PVarRec = ^TVarRec;
TVarRec = record
case Byte of
vtInteger: (VInteger: Integer; VType: Byte);
vtBoolean: (VBoolean: Boolean);
vtChar: (VChar: Char);
vtExtended: (VExtended: PExtended);
vtString: (VString: PShortString);
vtPointer: (VPointer: Pointer);
vtPChar: (VPChar: PChar);
vtObject: (VObject: TObject);
vtClass: (VClass: TClass);
vtWideChar: (VWideChar: WideChar);
vtPWideChar: (VPWideChar: PWideChar);
vtAnsiString: (VAnsiString: Pointer);
vtCurrency: (VCurrency: PCurrency);
vtVariant: (VVariant: PVariant);
vtInterface: (VInterface: Pointer);
vtWideString: (VWideString: Pointer);
vtInt64: (VInt64: PInt64);
end;

Поле VType определяет тип содержащихся в данном экземпляре записи TVarRec данных и может принимать одно приведенных значений.

Поскольку массив констант способен передавать данные разных типов, это может вызвать определенные затруднения при создании обрабатывающей полученные параметры функции или процедуры. В качестве примера работы с таким массивом рассмотрим реализацию процедуры WhatHaveIGot, которая просматривает элементы полученного массива параметров и выводит их тип.

procedure WhatHaveIGot( A: array of const );
var
i: integer;
TypeStr: string;
begin
for i := Low(A) to High(A) do
begin
case A[i].VType of
vtInteger : TypeStr := ‘Integer’;
vtBoolean : TypeStr := ‘Boolean’;
vtChar : TypeStr := ‘Char’;
vtExtended : TypeStr := ‘Extended’;
vtString : TypeStr := ‘String’;
vtPointer : TypeStr := ‘Pointer’;
vtPChar : TypeStr := ‘PChar’;
vtObject : TypeStr := ‘Object’;
vt ;
vtW ;
vtPW ;
vtAnsiString : TypeStr := ‘AnsiString’;
vtCurrency : TypeStr := ‘Currency’;
vtVariant : TypeStr := ‘Variant’;
vtInterface : TypeStr := ‘Interface’;
vtW ;
vtInt64 : TypeStr := ‘Int64’;
end;
ShowMessage( Format( ‘Array item %d is a %s’, [i, TypeStr] ) );
end;
end;

Значения параметров по умолчанию

В Delphi есть одна очень полезная возможность — использование значений параметров по умолчанию. Она позволяет установить принимаемое по умолчанию значение параметра процедуры или функции. Это значение будет использоваться в тех случаях, когда вызов процедуры или функции производится без указания значения данного параметра. В объявлении процедуры или функции принимаемое по умолчанию значение параметра указывается после знака равенства, следующего после его имени. Поясним это на следующем примере:

procedure HasDefVal( s: string; i: integer = 0 );

Подобное объявление означает, что процедура HasDefVal может быть вызвана двумя путями. В первом случае — как обычно, с указанием обоих параметров:

procedure HasDefVal( ‘Hello’, 26 );

Во втором случае можно задать только значение параметра s, а для параметра i использовать значение, установленное по умолчанию:

procedure HasDefVal( ‘Hello’ );

При использовании значении параметров по умолчанию следует помнить о нескольких приведенных ниже правилах:

  • Параметры, имеющие значения по умолчанию, должны располагаться в конце списка параметров. Параметр без значения по умолчанию не должен встречаться в списке после параметра, имеющего значение по умолчанию.
  • Значения по умолчанию могут присваиваться только параметрам обычных типов, указателям или множествам.
  • Значение по умолчанию может передаваться только по значению либо с модификатором const. Оно не может быть ссылкой или нетипизированным параметром.

Одним из важных преимуществ применения значений параметров по умолчанию является простота расширения функциональных возможностей уже имеющихся процедур и функции с соблюдением обратной совместимости. Предположим, на рынок программных продуктов была выпущена программа, ключевым звеном которой является функция сложения двух целых величин:

function Add( I1, I2: integer ): integer;
begin
Result := I1 + I2;
end;

Предположим также, что исследования показали целесообразность добавления в программу возможности сложения трех чисел. Однако замена имеющейся функции функцией сложения трех чисел приведет к тому, что вам придется переправлять немало текста, который перестанет компилироваться из-за внесения в функцию еще одного параметра. Однако при использовании значений параметров по умолчанию проблема решается легко и просто. Достаточно изменить объявление функции так, как показано ниже.

function Add( I1, I2: integer; I3: integer = 0 ): integer;
begin
Result := I1 + I2 + I3;
end;

Директива

Директива <$X->запрещает вызов функций как процедур (с игнорированием возвращаемого результата). По умолчанию этот режим включен (<$X+>). Так вот, запомните, использование переменной Result недопустимо при сброшенном флажке опции Extended Syntax, расположенном во вкладке Compiler диалогового окна Project Options, или при указании директивы компилятора <$X->.

В каждой функции языка Objecl Pascal существует локальная переменная с именем Result, предназначенная для размещения возвращаемого значения. Кроме того, вернуть значение из функции можно также путем присвоения значения переменной, имеющей то же имя, что и данная функция. Это стандартный синтаксис языка Pascal, сохранившийся от его предыдущих версий. При использовании в теле функции переменной с ее именем не забывайте, что существуют большие отличия в обработке этого имени — все зависит от того, где она расположена — в левой части оператора присвоения или же в любом другом месте текста функции. Если имя функции указано в левой части оператора присвоения, то предполагается, что назначается возвращаемое функцией значение. Во всех других случаях предполагается, что осуществляется рекурсивный вызов этой функции.

Процедура и функция — это ключевые понятия в любом языке программирования, без которых не обходится ни одна серьезная программа. И поэтому очень важно иметь полное понимание о механизме их работы.

Обучающий курс. 12. Функции и процедуры в Delphi. Математические вычисления. Случайные числа

Сегодня мы поговорим о процедурах и функциях в Delphi . Что такое процедура? Это маленькая программа, выполняющая операции с указанными данными. Различают собственно процедуры и функции. Их основное отличие — процедура просто совершает какие-либо операции, а функция обязательно выдаёт какой-либо результат в результате своей работы. Существует огромное количество стандартных процедур и функций. Подпрограммы (так называют процедуры и функции) можно писать и самостоятельно, но об этом речь пойдёт позже. Сейчас нам нужно научиться работать с готовыми функциями.

Общие сведения о подпрограммах

Фактически, подпрограмма — это такая же полноценная программа, просто работает она не отдельно, не сама по себе, а включена в другую программу.
У подпрограммы всегда есть имя. Имя строится по тем же правилам, что и идентифмкатор. Как правило, имена даются вполне логичные. Например, если функция находит максимальное из нескольких чисел, то её логично назвать Max .
Подпрограммы могут иметь входные параметры. Входные параметры — это данные, которые сообщаются подпрограмме до начала её работы, а в процессе выполнения эти данные могут использоваться. Тем не менее, подпрограммы могут и не иметь входных параметров. Входные параметры также называют аргументами. Например, функции, которая узнаёт текущее время, никакие дополнительные параметры не нужны, а вот если функция считает факториал, то обязательно должно быть число, для которого он считается.
Как было сказано выше, функция выдаёт какое-то значение в результате своей работы. Процедура в общем случае значения не выдаёт.

Вызов подпрограмм

Вызываются подпрограммы по имени. Если подпрограмме требуется передать какие-либо параметры, то они указываются в скобках после имени подпрограммы через запятую. Если входные параметры отсутствуют, достаточно просто написать имя подпрограммы, либо оставить скобки пустыми. В случае, если работа происходит с функцией, результат можно «сохранить» в какой-то переменной, просто «присвоив» этой переменной функцию.

Обратите внимание: работа с функциями происходит как с обычными переменными, просто их значения вычисляются «на лету».

Функции математических вычислений

Эти функции работают с числовыми данными. Как правило, входным параметром является какое-то число, а выходным — результат вычисления. Практически везде аргумент является либо целым числом ( Integer ), либо вещественным ( Real ). Возвращаемое значение — тоже число. Рассмотрим некоторые из этих функций:

Abs(x) — модуль (абсолютное значение) указанного числа x . Пример: Abs(-5) = 5 .

Sin(x) — синус числа x . Здесь x — угол в радианах (не в градусах!). Пример: Sin(Pi/2) = 1 .

Cos(x) — косинус числа x . Аналогично, x — радианы. Пример: Cos(Pi) = -1 .

Exp(x) — экспонента, e x ( e в степени x ).

Ln(x) — натуральный логарифм числа x . Пример: Ln(Exp(2)) = 2 .

Sqr(x) — квадрат числа x ( x 2 ). Пример: Sqr(5) = 25 .

Sqrt(x) — квадратный корень числа x . Пример: Sqrt(64) = 8 .

Int(x) — целая часть числа x . Пример: Int(1.234) = 1 .

Frac(x) — дробная часть числа x . Пример: Frac(1.234) = 0.234 .

Round(x) — округление аргумента до ближайшего целого числа. Пример: Round(1.234) = 1 .

Trunc(x) — целая часть вещественного числа x. Пример: Trunc(1.234) = 1 .

Pred(x) — предыдущее значение x (например, для x = 2 это 1 ).

Succ(x) — следующее значение x (для x = 2 это 3 ).

Odd(x) — проверка аргумента на нечётность. Функция возвращает значение True , если аргумент является нечётным числом и False — если чётным. Пример: Odd(5) = True .

Предсказываю вопрос: в чём отличие Int() от Trunc() ? А отличие в том, что Int() возвращает число вещественного типа, а Trunc() — целочисленного .

Это лишь часть всех доступных функций. На самом деле их гораздо больше. Но помимо функций есть ещё процедуры.

Процедуры работы с числами

Поскольку процедуры в результате работы не выдают никакого значения, процедуры работы с числами просто изменяют переданные им параметры-переменные.

Inc(x) — увеличение аргумента на единицу. Фактически, это то же самое, что x:=x+1 . Тем не менее, рекомендуется использовать именно эту функцию, так как работает она быстрее.
Примечание: под понятием «быстрее» подразумевается, конечно, быстрота «компьютерная». Компьютер выполняет миллионы операций в секунду и для человека такие вещи незаметны.

Inc(x,n) — увеличение аргумента на число n . Эквивалентно записи x:=x+n .

На самом деле, это не две разные процедуры — просто параметр n является необязательным. Да, бывают необязательные параметры, которые можно указать, а можно и не указывать. Если они отсутствуют, то просто берётся какое-то значение по умолчанию. В данном случае n по умолчанию имеет значение 1 .

Dec(x,n) — уменьшение аргумента на n единиц. Точно также, как и в Inc , параметр n является необязательным. Эквивалентно записи x:=x-n .

В документации необязательные параметры обычно заключают в квадратные скобки, т.е. обычно пишут Inc(x , [n]) . Обратите внимание: это лишь условное обозначение, которое создано с целью узнавания, что параметр необязательный. В программном коде никаких скобок нет и быть не может.

Не хватает стандартных математических функций?

Существует дополнительный модуль с именем Math , в котором содержится большое число математических функций. Например, если нужно посчитать гиперболический арксеканс числа, то мучаться и описывать способ его вычисления вручную не придётся — есть готовая функция ArcSecH() .
Чтобы подключить модуль Math , откройте исходный код модуля. Для этого, когда открыта форма, следует нажать F12 , либо выбрать пункт меню View » Toggle Form/Unit . Далее нужно переместиться в самое начала модуля в раздел uses . В этом разделе через запятую описываются имена подключённых модулей. Как можно заметить, даже при наличии пустой формы несколько модулей уже подключены. В этот список и следует добавить Math :

Всё, теперь в Вашем распоряжении большое количество математических функций.

Пример комбинирования функций

Раз уж речь пошла о математических функциях, пусть пример будет на них и основан. Допустим, у нас есть такая сравнительно сложная функция:

Нам нужно создать программу, которая бы вычисляла значение этой функции по заданным числам x и y . Рассмотрим поэтапно элементы функции:
1) Возведение числа e в степень, модуль — функции Exp() и Abs() соответственно.
2) Натуральный логарифм — функция Ln() .
3) Число e . Часто спрашивают — как получить число e ? Ведь это, по сути, такая же константа, как и число пи . Но она не объявлена. А ответ прост: e = e 1 , поэтому e — это exp(1) .
4) Тангенс — функция Tan() .
Всё необходимое у нас есть, поэтому можно приступить к записи. Главное — не забывать заключать в скобки отдельные элементы формулы, чтобы порядок действий сохранился (в нашем примере это не потребуется).

Как возвести число в степень?

Почему я останавливаюсь на таких вопросах? Просто они очень часто возникают у новичков и не каждый может догадаться, как выполнить требуемую операцию.

Способ 1. X y можно преобразовать к виду e ln(x)⋅y . Тогда возведение в степень можно записать так:

Способ 2. В модуле Math есть функция для возведения в степень — Power . У функции 2 аргумента — основание и показатель степени. Запись, соответственно, следующая :=Power(x,y);

Случайные числа

Зачем нужны случайные числа? Как правило, чтобы проверить результаты какого-то эксперимента при различных условиях. На основе случайных чисел можно вычислять различные вероятности. Во всех языках программирования есть возможность использовать случайные числа.

В Pascal (и Delphi соответственно) случайные числа генерируются функцией Random . Функция принимает один параметр, да и тот необязательный. Этот параметр позволяет указать границу диапазона, из которого будет выбрано случайное число. Итак: Random([Range: Integer]) . Если Range указан, то число выбирается из диапазона 0 ( X — само случайное число, которое будет получено). Обратите внимание, что сама граница в диапазон не включается, т.е. Random(10) никогда не выдаст число 10 , хотя 0 — запросто. Если диапазон не указан, то он считается равным единице, т.е. 0 .

Пример. Создадим форму с кнопкой, но пусть кнопка каждую секунду изменяет своё положение. Воспользуемся таймером ( TTimer , вкладка System палитры компонент). Interval оставим без изменения ( 1 сек. ), а вот в обработчике запрограммируем произвольное изменение положения кнопки на форме. Разберёмся, что нам нужно:
1) Позиция кнопки на форме. Как Вы уже знаете, за положение отвечают свойства Left и Top , которые указывают положение левого верхнего угла кнопки относительно левого верхнего угла формы. Именно этим свойствам мы будем присваивать произвольные значения.
2) Каков будет диапазон для генерации случайных чисел? Очевидно, что кнопка не должна уйти за границы формы. Значит нам нужно подключить размеры самой формы, т.е. её высоту и ширину. В данном случае будем использовать не Width и Height , а ClientWidth и ClientHeight , так как в первые свойства входят заголовок и границы формы, а это лишние пиксели, за которые кнопка может вылезти. Однако и это ещё не всё — из этих размеров мы должны вычесть соответственно ширину и высоту самой кнопки, иначе она может частично скрыться за границами.
Пишем обработчик:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Button1.Left := Random(ClientWidth-Button1.Width);
Button1.Top := Random(ClientHeight-Button1.Height)
end ;

Запускаем программу и наблюдаем. Кнопка действительно прыгает с места на место. Но есть один крайне неприятный момент: запустите программу несколько раз и понаблюдайте за точками, в которые попадает кнопка. Вы сразу заметите, что каждый раз кнопка перемещается по одним и тем же точкам.

Отчего это происходит? Дело в том, что числа, выдаваемые функцией Random() на самом деле не являются случайными — они псевдослучайны , т.е. наблюдается повторение. К счастью, решение есть — специальная процедура Randomize() инициализирует генератор случайных чисел, который выдаёт действительно случайные числа. Вызвать эту процедуру нужно всего один раз за время работы программы — обычно это делается при запуске (например, в событии OnCreate формы). Процедура не принимает никаких параметров. Вернёмся к нашему примеру:

procedure TForm1.FormCreate(Sender: TObject);
begin
Randomize
end ;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Button1.Left := Random(ClientWidth-Button1.Width);
Button1.Top := Random(ClientHeight-Button1.Height)
end ;

Теперь кнопка будет прыгать совершенно по разным точкам при каждом запуске программы.

Кстати, можно дописать скобки к названию процедуры — от этого работа не изменится: Randomize; = Randomize(); А запись немного красивее (на мой взгляд).

Дополнительные возможности редактора кода

В редакторе кода есть одна очень хорошая вещь — после того, как написано имя процедуры или функции и открыта скобка, появляется подсказка со всеми параметрами, которые подпрограмма принимает. Более того, там же указаны и типы данных всех параметров. Попробуйте, к примеру, набрать Inc( и подождать секунду — появится подсказка:

Как и было отмечено выше, второй параметр является необязательным и он заключен в квадратные скобки.

Такие подсказки позволяют моментально узнать, что подпрограмма требует на вход. При этом не придётся открывать модуль, где находится функция, либо искать её описание в документации или справочной системе.

Если функции или процедуре входные параметры не нужны, подсказка всё равно появится и сообщит об этом:

Если после набора имени и скобки подсказка не появилась, то и при компиляции программы скорее всего возникнет ошибка. Причиной, по которой компилятор не смог найти указанную функцию или процедуру, может быть ошибка при наборе имени, либо модуль, в котором описана подпрограмма, не подключен.
Ошибки при компиляции появляются внизу окна редактора кода с указанием номера строки, где обнаружена ошибка и описанием самой ошибки.
Попробуем запросить процедуру Randomiz (например, мы случайно недописали букву » e » на конце):

Строка с ошибкой выделилась, а внизу появился её номер ( 28 ) и описание — Undeclared identifier (неописанный идентификатор).

Заключение

В этом уроке охвачено сразу несколько тем — знакомство с процедурами и функциями, обзор математических функций и процедур, модуль Math, работа со случайными числами, а также удобства редактора кода и выделение ошибок при компиляции.

Илон Маск рекомендует:  Как создать собственную cms
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL