Каким должен быть язык программирования? Анализ и критика Описание языка Компилятор
Отечественные разработки Cтатьи на компьютерные темы Компьютерный юмор Новости и прочее

Типы в инженерных задачах

Введение

Введение

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

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

            Могут возразить, что я не вижу смысла в таких типах потому, что в старых языках (вроде используемого мною PL/1) вообще не было типизации в современном понимании. Нет, понятие типа все-таки было. Например, если в том же PL/1 описать два несовпадающих объекта пусть даже одинакового объема и попытаться присвоить один другому, то при компиляции получится предсказуемое сообщение об ошибке.
Ошибка несоответствия типов в PL/1 при компиляции.
Ошибка несоответствия типов в PL/1 при компиляции.
            Тогда за какое же отсутствие типов критиковали старые языки, в том числе PL/1? Например, за возможность присвоения объекта «строка» объекту «число в формате IEEE-754». Ведь в этом случае ошибок при компиляции уже не будет. Верно, ошибки не будет. Но в моем понимании это вовсе не разные типы. Это всего лишь работа с числовыми значениями в разном представлении. Просто здесь число в виде строки цифр и специальных символов переводится в число же, но в формате IEEE-754. А сам тип объекта остается одним и тем же — числовым. Но в том же PL/1 вполне можно проследить и разницу между «строкой» и «числом». Например:
Declare (S1, S2) char(*) varying;
S1=S1||S2;
S1=S1+S2;
            В первом случае происходит склейка двух строк в одну, а во втором каждая строка сначала преобразуется в числовое значение, затем эти значения складываются и результат снова преобразуется в строку цифр и, возможно, специальных знаков. Правила языка были разработаны таким образом, чтобы преобразование числовых значений из одной формы представления в другую проходило по возможности без потери точности. Непонимание, что транслятор постоянно применяет эти правила и приводит к неверным утверждениям об отсутствии типов в PL/1.

            Огорчает, что «абстрактные» типы, обычно представляемые в целых числах, часто создают лишь иллюзию упрощения задачи, не помогая её решению. Причем внимание к типизации все время возрастает, а польза от их применения, по крайней мере, в «инженерных» задачах — сомнительна. Если тип — целое число, его можно только сравнить с другими типами, а для перечисляемых типов — определить предыдущий/следующий из списка. В учебниках охотно приводят как пример перечисляемого типа «день недели»: понедельник, вторник… Но что это дает, например, для практической задачи определения дня недели по заданной дате? Тип «день недели» никак не помогает, зато помогает формула:
День_недели=([2.6*Месяц-0.2]+День+Год+[Год/4]+[Столетие/4]-2*Столетие) mod 7
где квадратные скобки означают целую часть числа.

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

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

            Даже один из авторов языка Ада Н. Джехани в ретроспективе сожалел, что в этот язык изначально им не была встроена система типов в виде «единиц измерений» [1]. Для класса «инженерных» задач эта идея — использовать как систему типов Международную систему единиц СИ, всегда казалась мне очевидной и потенциально полезной, но почему-то нигде в современных распространенных языках не реализованной, за исключением некоторых возможностей в Matlab. И я решил поэкспериментировать со своим транслятором PL/1 [2] и добавить новую типизацию не в виде абстрактных понятий, а прямо в виде размерностей из базовых величин СИ, и затем на примере реальной задачи посмотреть какие плюсы и минусы это даст программисту, а также оценить сложность доработок транслятора.

Физический смысл типов в инженерных задачах

            Приписывая при решении «инженерной» задачи объектам программы не абстрактный, а физический смысл (и используя как тип размерность, т.е. выражение производной величины через первичные), мы сразу добавляем хорошо определенное множество зависимостей для этих объектов, а значит, облегчаем транслятору автоматическую проверку корректности действий и, тем самым, повышаем надежность программы.

            При этом теоретическое обоснование системы независимых «физических» типов уже давно имеется в виде успешно применяемой теории размерности, основная теорема («пи-теорема») которой формулируется следующим образом [3]: соотношение, не зависящее от выбора единиц измерения между (n+1) размерными величинами a, a1, a2,…an, k из которых имеют независимые размерности, может быть представлено в виде соотношения между (n+1-k) величинами П, П1, П2,… Пn-k, представляющими собой безразмерные комбинации (n+1) размерных величин.

            Основной смысл пи-теоремы состоит в том, что всякое физическое соотношение между размерными величинами можно сформулировать как соотношение между безразмерными величинами.

            Следовательно, поскольку в СИ независимыми являются лишь семь физических величин:
  • длина L (единица — метр),
  • масса M (единица — килограмм),
  • время T (единица — секунда),
  • термодинамическая температура Θ (единица — Кельвин),
  • сила электрического тока I (единица — ампер),
  • сила света J (единица — кандела),
  • количество вещества N (единица — моль),
то в программе любой переменной, которой мы приписали физический смысл, может быть сопоставлен «физический» же тип в виде размерности из степенного одночлена, выраженного через основные единицы: [x]=Ll Mm Tt Θθ Ii Jj Nn.

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

Масштабный коэффициент в «физических» типах

            На практике величины, имеющие физический смысл, часто задаются в производных единицах измерения, отличающихся от базовых единиц масштабным коэффициентом. Например, длины — в км, площади — в Га и т.д. Поэтому целесообразно ввести в представление «физических» типов ещё и масштабный коэффициент в виде одного числа в формате IEEE-754.

            Наличие такого коэффициента позволит транслятору автоматически учитывать масштабы при генерировании операций для выражений. Например, если переменным X1, X2, X3 приписаны типы соответственно [км], [см] и [мм], то при вычислении выражения X1=X2+X3, транслятор должен автоматически добавить операции умножения X2 на 0.01 и X3 на 0.001, а затем результат сложения перед присваиванием X1 ещё разделить на 1000.

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

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

Дополнительные величины в «физических» типах

            Хотя в СИ имеется лишь семь базовых величин, на практике используются ещё две вспомогательные величины — плоский угол (единица — радиан) и телесный угол (единица — стерадиан).

            Здесь наблюдается некоторое противоречие с точки зрения формального определения типа. В самом деле, радиан и стерадиан — по определению безразмерные величины и могут быть использованы или не использованы в выражениях для других производных единиц СИ. Однако в некоторых случаях они ведут себя как обычные (размерные) величины. Например, в PL/1 имеется встроенная функция sin, входным параметром которой должно быть выражение в радианах и функция sind, входным параметром которой должно быть выражение в градусах. Переменная с «физическим» типом «градус» отличается от переменной с «физическим» типом «радиан», масштабным коэффициентом π/180.

            Таким образом, целесообразно и радианы и стерадианы также включать в степенной одночлен представления «физического» типа и, например, проверять, что функция sin берется от величины в радианах или в градусах, а не в метрах. Но тогда формально возникает конфликт размерностей при других вычислениях, например:
W=φ/t;    // угловая скорость (угол делится на время)
V=R*W;    // линейная скорость (радиус поворота умножается на угловую скорость)
            В самом деле, если угол φ имеет «физический» тип «радиан», то получается, что угловая скорость W имеет «физический» тип «радиан в секунду», а линейная скорость после умножения на радиус — «метр на радиан в секунду», что не соответствует требуемой размерности скорости «метр в секунду».

            Поэтому хотя вспомогательные величины радиан и стерадиан действительно также представлены в степенном одночлене «физического» типа, но ведут себя не совсем так, как семь остальных базовых величин. Они считаются «размерными» величинами, только если остальные величины в одночлене имеют нулевые показатели степени (т.е. отсутствуют). Как только при вычислениях появляется любая другая величина — радиан и стерадиан «сокращаются», т.е. их показатель степени транслятором обнуляется. Тогда в приведенном примере выражение φ/t (и угловая скорость W) получает «физический» тип «единица, деленная на секунду», а выражение R*W правильный «физический» тип скорости «метр в секунду». Но при этом выражение, например, sin(2*φ) по-прежнему можно проверить на корректный «физический» тип аргумента «радиан».

Внутреннее представление «физического» типа в трансляторе

            Исходя из приведенных выше теоретических и практических соображений, каждой переменной программы, которой может быть приписан некоторый физический смысл, программистом может быть присвоен универсальный «физический» тип из величин СИ. Данный тип в таблице транслятора PL/1 представлен в виде одного масштабного коэффициента в формате IEEE-754 и занимающего восемь байт, а также девяти показателей степени основных и вспомогательных величин в смысле единиц СИ.

            Поскольку вычисления в «инженерных» задачах проводятся и с дробными степенями, например, Z=SQRT(X**2+Y**2), то показатели степени в универсальном «физическом» типе представлены рациональными (и возможно неправильными) дробями. При этом байт занимает числитель и байт знаменатель. Таким образом, показатели степени в трансляторе могут быть представлены числами от -128 до 127, а в целом каждый «физический» тип переменной занимает в таблице транслятора 8+9*2=26 байт.

Действия с «физическими» типами при вычислении выражений

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

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

            При делении переменных показатели степеней их «физических» типов вычитаются.

            При возведении переменной в степень-константу показатели степеней «физического» типа умножаются на эту константу. При этом возведение в нецелую степень или в степень-переменную для «физического» типа считается ошибкой, за исключением случая представления степени-константы в виде дроби. Например, в выражении X**(1e0/3e0) показатели степени «физического» типа переменной X будут умножены на дробь 1/3, т.е. в данном случае знаменатели степеней будут умножены на три.

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

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

            Задание «физических» типов в исходном тексте программы

            При доработке транслятора для удобства задания «физических» типов с сохранением возможности трансляции уже написанных программ (без таких типов), были использованы символы квадратных скобок, ранее вообще не применявшиеся в языке PL/1, например:
Declare V float(53) [м/с];
            Внутри квадратных скобок могут быть записаны произвольные выражения, состоящие из скобок, знаков умножения, деления, возведения в степень, числовых констант и девяти имен базовых и вспомогательных величин СИ: м, кг, с, а, к, моль, кд, рад, ср. Для угловых величин допустимо также имя «ПИ». Например:
Declare Mu float(53) [(1000*m)**3/c**2];
Declare Fi float(53) [пи/180*рад];
            Встроенная таблица «физических» типов в трансляторе имеет лишь девять первых заполненных строк перечисленными выше базовыми величинами, однако с помощью препроцессорного оператора замены %replace в неё можно добавлять произвольное число «нестандартных» типов, например:
%Replace
[км]   by [1000*м],
[час]  by [3600*c],
[миля] by [1852*м],
[узел] by [миля/час];
…
Declare
скорость       float(53) [км/час],
скорость_судна float(53) [узел];
            При этом после выполнения оператора %Replace имена «км», «час», «миля» и «узел» становятся допустимыми только внутри квадратных скобок описания «физического» типа, но не в остальном тексте программы.

Присваивание переменным с «физическими» типами начальных значений

            При обработке оператора присваивания переменной с «физическим» типом транслятор проверяет, что показатели степени девяти величин СИ в представлении типа в левой и правой части присваивания совпадают. Но как быть при присваивании переменной начального значения не выражения, а, например, константы?

            Вроде бы напрашивается непосредственное указание «физического» типа у констант прямо в операторах программы, например:
V=10 [км/час];
            Но мне такой подход не кажется логичным. Все-таки числовые константы, записываемые непосредственно в физических уравнениях не должны иметь собственной размерности. Это удел переменных, даже, если они и не меняют в данном конкретном случае своих величин. Поэтому инициализация значений в доработанном трансляторе выполняется так:
Declare 
// константы
g  float(53) static init(9.81e0) [м/c**2],
v0 float(53) static init(10e0)   [км/час],
// переменные
m  float(53) [кг],
v  float(53) [км/час],
F  float(53) [кг*м/с**2];
…
v=v0;  F=g*m;
Исключение составляет константа 0. Её «физический» тип может быть любым:
v=0;   F,m=0;

Чтение и запись переменных с «физическими» типами

            В файловом обмене языка PL/1 существует два вида чтения/записи объектов: двоичный и текстовый, реализуемые соответственно операторами read/write и get/put.

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

            А вот в другом случае появляется несколько непривычное свойство вывода переменных с «физическими» типами. Поскольку в общем случае текстового вывода выдаваемый объект — это выражение, то для переменных с «физическими» типами в нем автоматически будут учтены масштабные коэффициенты, а, следовательно, выражение всегда будет выведено в базовых единицах СИ, например, в метрах, даже когда выводится одна переменная и она задана в километрах или в миллиметрах.

            Для того чтобы операторы put и get оставались «зеркальными» транслятор автоматически учитывает масштабный коэффициент переменной и при чтении её оператором get, т.е. при чтении также подразумевается, что значения хранятся в файлах в базовых единицах СИ.

            Если все же необходим текстовый обмен без учета масштабных коэффициентов, то в PL/1 это можно реализовать, используя т.н. «наложенные» переменные, т.е. описав переменные без «физических» типов по тем же адресам памяти, что и переменные с «физическими» типами, например, в случае:
Declare
X1 float(53) static init(10e0) [км],
X2 float(53) defined(X1);

put skip list(X1,X2);
будут выданы значения 10000 и 10.

Встроенная переменная ?TYPE для выражений с «физическими» типами

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

            В самом деле, вычислять «физический» тип для одной переменной с помощью встроенной функции довольно бессмысленно, поскольку эта же переменная описана с этим же «физическим» типом здесь же, в исходном тексте. «Физический» тип обычно нужен при выводе результатов в виде выражений, но тогда выражение транслятору придется вычислять два раза, например:
put skip list(s/t,type(s/t));
            Поэтому для вывода удобнее использовать встроенную переменную, а не функцию, например при выполнении оператора вывода в данном примере:
Declare
s  float(53) static init(10) [км],
t  float(53) static init(5)  [час];
…
put skip list(s,?type,t,?type,s/t,?type);
будут выданы следующие значения
1.00000000000000E+004 M  1.80000000000000E+004 C  5.55555555555555E-001 M*C**-1
конец программы

«Физические» типы формальных параметров подпрограмм

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

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

            Также, разумеется, «физический» тип может иметь возвращаемое подпрограммой значение:
Declare
//модуль радиус-вектора
Vmod entry((3) float(53)[км]) returns(float(53)[км]);
            Поскольку на практике используются и подпрограммы с полиморфными типами, я допустил задание в формальных параметрах неопределенного «физического» типа (с помощью знака «?»), при котором проверки на совпадение и учет масштабных коэффициентов отключаются.
Declare
//модуль любого вектора
Vmod0 entry((3) float(53)[?]) returns(float(53)[?]);
            Еще один особый случай представляет встроенная функция квадратного корня SQRT. Она, разумеется, тоже имеет неопределенный «физический» тип формального аргумента, но возвращает всегда такой же тип как у фактического аргумента и в степени ½.

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

Отладочные средства для «физических» типов

            Кроме встроенной переменной ?TYPE, есть ещё два отладочных средства. Это возможность вывести всю таблицу переменных программы, включая теперь и их «физические» типы с масштабными коэффициентами и собственно сообщения при компиляции о несоответствии типов в вычисляемых выражениях (рис. 3). В данном случае в небольшом тесте, приведенном ниже, в операторе сравнения «физические» типы справа и слева оказались не равны.
test:proc main;

%replace
[км]  BY [1000*м],
[час] BY [3600*с];

declare

s  float(53) static init(10) [км],
t  float(53) static init(5)  [час],
v  float(53) [км/час];

if s*t>v*t then stop;
…
            Вывод транслятором таблицы переменных с «физическими» типами и сообщения о несоответствии «физических» типов в операции сравнения:
a 00000000 TEST ПРОЦЕДУРА ПАРАМЕТРЫ(0) ОБЩЕЕ НЕИЗМЕНЯЕМОЕ
БЛОК В СТРОКЕ 3, ВЫДЕЛЕНО ПАМЯТИ 8 БАЙТ
с 00000000 S ВЕЩ. ЧИСЛО ДВОИЧНОЕ(53) СО ЗНАЧЕНИЕМ ПОСТОЯННОЕ [1.0000000E+03*M]
с 00000000 T ВЕЩ. ЧИСЛО ДВОИЧНОЕ(53) СО ЗНАЧЕНИЕМ ПОСТОЯННОЕ [3.6000000E+03*С]
с 00000000 V ВЕЩ. ЧИСЛО ДВОИЧНОЕ(53) ВРЕМЕННОЕ [2.7777777E-01*M*С**-1]
*КОНЕЦ*
  13 с      if s*t>v*t then stop;
P3M. НЕ=                 ?
M*C # M

Пример применения «физических» типов

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

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

            Примеры изменений исходного текста данной программы приведены ниже. а) Потребовалось ввести ряд переменных с типами вместо ранее безразмерных констант, например:
// СКОРОСТЬ ВРАЩЕНИЯ ЗЕМЛИ 
WEarth  float(53) static init(0.000072921158e0)      [РАД/C],

// ДВА ПИ 
Dpi     float(53) static init(6.28318530717958648e0) [РАД], 

// Epsilon/Mu 
Em      float(53) static init(66072.1866e0)          [KM**2],

// ГРАВИТАЦИОННЫЙ ПОТЕНЦИАЛ 
Mu      float(53) static init(398600.4e0)            [KM**3/C**2],

// ПОЛУОСЬ ДЛЯ СРЕДНЕЙ ВЫСОТЫ 358 КМ 
Am      float(53) static init(6736e0)                [KM],

//ЭКВАТОРИАЛЬНЫЙ РАДИУС ЗЕМЛИ 
Re      float(53) static init(6378.137e0)            [KM],
б) Потребовалось убрать ряд приведений масштабов переменных, например, было:
//---- ПРИВЕДЕНИЕ МАСШТАБОВ К КМ И +-180 ----

do i=1 to 3;
   vsg(i)=vsg0(i)/1000e0;       // ПЕРЕВЕЛИ В КМ
   vrg(i)=vrg0(i)/1000e0;       // ПЕРЕВЕЛИ В КМ
   if Lamseans(i) > 180e0 then Lamseans(i)-=360e0;
end i;
Стало:
//---- ПРИВЕДЕНИЕ МАСШТАБОВ К КМ И +-180 ----

do i=1 to 3;
   vsg(i)=vsg0(i);     // АВТОМАТИЧЕСКИЙ ПЕРЕВОД В КМ
   vrg(i)=vrg0(i);     // АВТОМАТИЧЕСКИЙ ПЕРЕВОД В КМ
   if Lamseans(i) > У_180 then Lamseans(i)-=У_360;
end i;
Было:
BetaBal=60e0*(per2-per1)/(te2s-te1s)/2e0;   // ПЕРИОД БЫЛ В МИНУТАХ
Стало:
BetaBal=(per2-per1)/(te2s-te1s)/2e0;        // ПЕРИОД БЫЛ В МИНУТАХ
в) Некоторые произвольно разбитые на части формулы потребовалось свернуть, чтобы не вводить промежуточных переменных с нестандартной размерностью, например, было:
//---- ТЕКУЩИЙ РАДИУС ДЛЯ РАСЧЕТА ВЫСОТЫ ----

Radius  = J3-et1+dz1*dz1+J4*cos(ArgLat+ArgLat);
Radius *= Axe*(1e0+J7*tp);
Стало:
//---- ТЕКУЩИЙ РАДИУС ДЛЯ РАСЧЕТА ВЫСОТЫ ----

Radius  = Axe*(1e0+J7*tp)* (J3-et1+dz1*dz1+J4*cos(ArgLat+ArgLat));
            Однако большей частью исходный текст остался без изменений. В результате тестовых расчетов были получены те же результаты, что и у исходной программы, при трансляции сообщений о несоответствии типов не выдавалось, например, самая громоздкая из использованных формул дала корректную размерность длины:
//---- ОЦЕНКА ПОЛУОСИ ПО ЗНАЧЕНИЮ ПЕРИОДА ----

do AxeOfPer=Am, i=1 to 4;                   // НАЧИНАЕМ С ВЫСОТЫ 358 КМ
 AxeOfPer=((Period/Dpi)**2*Mu)**(1e0/3e0)
         /(1e0-2e0/3e0*Em/AxeOfPer/AxeOfPer*(4e0*CosIncl*CosIncl-1e0));
end;
            Однако одна логическая ловушка с точки зрения размерностей в программе все-таки нашлась:
//---- ШИРОТА В ГРАДУСАХ С УЧЕТОМ ЭЛЛИПСОИДНОСТИ ЗЕМЛИ ----

Fi = Fi + Alz*sin(2e0*Fi);
Здесь Alz — безразмерный коэффициент сжатия земного эллипсоида, равный 1/298.257. Получается, что в формуле угол Fi в радианах складывается с заведомо безразмерным синусом, т.е. несоответствие размерности. Так сказалось формальное представление углов условно размерной величиной «радиан», несмотря на то, что реальный радиан величина безразмерная. Для формального же преодоления этого несоответствия в формуле пришлось дополнительно умножить синус на переменную с «физическим» типом «радиан» и единичным значением.

Заключение

            Встраивание в транслятор языка PL/1 дополнительной типизации и назначение нового свойства переменным, определенного как «физические» типы в виде базовых и вспомогательных единиц Международной системы СИ позволило:
  • автоматически проверять по размерности корректность записи уравнений, имеющих физический смысл;
  • автоматически учитывать различные несистемные единицы измерений, при этом организовать сами вычисления всегда в семи базовых и двух вспомогательных единицах СИ.
            Если внутреннее представление «абстрактного» типа — целое число, то с таким типом можно выполнять лишь простейшие действия, например, сравнивать на совпадение или определять предыдущий/следующий тип. Обычно автоматически при вычислениях такой тип не меняется.

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

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

            Несмотря на то, что некоторые действия в программе из-за новых типов упрощаются, а некоторые встроенные функции (например, упомянутая выше sind) стали ненужными, в целом число операций в вычислениях может увеличиться (из-за добавления умножений на масштабные коэффициенты). Однако при этом проверки корректности программы облегчаются и её надежность возрастает.

            Как пример важности таких проверок корректности можно привести неудачу миссии Mars Climate Orbiter 23 сентября 1999 года из-за расчетов в «не тех» единицах измерения. Вполне вероятно, что если бы используемые трансляторы тогда имели бы механизм «физических» типов, подобный приведенному выше, а также автоматический вывод в системных единицах, можно было бы выполнять расчеты в злополучных «фунт-силах», но при этом избежать последующих разночтений с печальными последствиями.

Литература

1. Языки программирования Ада, Си, Паскаль. Сравнение и оценка. Под редакцией А. Фьюера, Н. Джехани. Радио и связь, 1989, с. 182.
2. Д.Ю.Караваев «К вопросу о совершенствовании языка программирования» RSDN Magazine #4 2011, с. 15-21.
3. А.С Романов, А.В. Семиколенов, С.Н. Тараненко, А.П. Шахорин Теория подобия и размерности. Пограничный слой. Электронное учебное издание МГТУ им. Н.Э. Баумана, 2011, с. 8.

Автор: Д.Ю.Караваев. 04.09.2017

Опубликовано: 2018.08.26, последняя правка: 2019.01.29    14:27

ОценитеОценки посетителей
   ██████████████ 6 (33.3%)
   ███████ 3 (16.6%)
   ████████████ 5 (27.7%)
   ██████████ 4 (22.2%)

Отзывы

✅  2018/09/22 12:32, Автор сайта          #0 

Оригинальный и смелый подход. Хотя с ним не согласен. Но это разум не согласен, а эмоциями я на Вашей стороне :) Вроде есть какой-то язык программирования, в котором можно указывать единицы измерения. Но на вскидку не скажу — уже не помню.

В принципе, с Вами можно согласиться, что 2 и «2» имеют один и тот же тип, просто у них разные представления. Современная типизация — это поиск ответов на вопрос: какое представление имеет некий кусок памяти с двоичными данными. В одних случаях информация о представлении (типе) доступна всегда, и во время исполнения тоже. В других случаях эта информация доступна только во время компиляции, тогда типизация считается статической, а не динамической. В случае статической типизации программа становится эффективнее.

Читая о Вашей «физической» типизации с 7 основными и 2 вспомогательными единицами измерения, я не понял, честно говоря, эта информация о типе доступна только во время компиляции или во время исполнения тоже? По идее, если формулы для расчёта чего-либо неизменны, то «физический» тип можно вычислить уже при компиляции.

✅  2018/10/24 14:21, Александр Коновалов aka Маздайщик          #1 

Хочу добавить, что в системе Mathcad поддержка размерностей именно так и реализована, как описано в статье. Последний раз пользовался Mathcad’ом примерно десять лет назад, тогда это уже было.

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

✅  2018/10/25 06:07, kt          #2 

«Именно так и реализована» — и так, и не так. С одной стороны — конечно, именно так, поскольку реализуется теория измерений физических величин, где все уже обосновано и выбрано. Но не совсем так, поскольку MathCad не язык программирования в привычном смысле, а интерпретатор. В нем реализация через предопределенные ПЕРЕМЕННЫЕ, а в языке — через СВОЙСТВА переменных (типы). В MatCad ограничивается допустимое множество имен, что не очень хорошо, например, уже нельзя назвать переменную m, поскольку это уже занято под метры. Например, скорость можно задать только через деление, которое хотя бы один раз, но физически выполняется V = S / T. А, чёрт, V — это, оказывается, вольты. Ну тогда H = S / T. Правда, H — индуктивность, но бог с ней.

А определение типа как V FLOAT [m/c] никакого деления не вызывает и никаких имен не ограничивает. Далее, например, можно просто читать V из файла и умножать на время, получая длины. Т.е. так и обойтись без единого деления. И все физические размерности исчезают после компиляции, остаются только масштабные коэффициенты, вставленные в операторы. А все проверки заканчиваются на этапе компиляции. Поэтому идеи все те же, а реализация все-таки другая.

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

✅  2019/01/02 07:23, rst256          #3 

Очень хорошая идея, обязательно поддержку таких типов в Lua добавлю.

✅  2019/10/15 08:58, kt          #4 

Пару лет назад я эту статью посылал в журнал «Программирование». И быстро получил вот такой ответ:


Уважаемый автор!

Мы с интересом прочитали Вашу статью. Ваш подход нам понравился, но мы бы хотели, чтобы публикуемая нами статья была более приближена к вопросам, интересующим максимально большую аудиторию наших читателей. Не могли бы Вы распространить описываемый в статье подход на более современные языки программирования, нежели такой популярный в прежние времена, но уже не так активно используемый в настоящее время язык PL/1? В частности, было бы интересно рассмотреть возможность применения описываемого подхода в сочетании с принципами объектно-ориентированного программирования.

Будем рады рассмотреть Вашу новую работу, ответственный секретарь редакционной коллегии журнала "Программирование"
Л. Е. Карпов

Не скрою, упоминание ООП в данной теме меня задело. Почему-то вспомнилась басня «Слон-живописец»:

Ценители пришли. Картину Слон открыл.
Кто дальше встал, кто подошел поближе.
"Ну, что же, — начал Крокодил, -
Пейзаж хорош! Но Нила я не вижу..."

Ничего не имею против ООП для соответствующего класса задач. Но здесь-то зачем этот «Нил»? Тем более, когда в сети вовсю идут статьи с заголовками типа: «Мнение: объектно-ориентированное программирование — катастрофа на триллион долларов».

✅  2019/10/20 16:16, Дмитрий          #5 

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

Вот пример кода, который давал в 2012 Страуструп (SI Units) :
Speed sp1 = 100m / 9.8s; // very fast for a human
Speed sp2 = 100m / 9.8s2; // error (m/s2 is acceleration)
Speed sp3 = 100 / 9.8s; // error (speed is m/s and 100 has no unit)
Acceleration acc = sp1/0.5s; // too fast for a human
И ещё пример оттуда же:
template<int M, int K, int S> struct Unit { // a unit in the MKS system 
enum { m=M, kg=K, s=S };
};

template<typename Unit> // a magnitude with a unit struct Value {
double val; // the magnitude
explicit Value(double d) : val(d) {} // construct a Value from a double
};

using Speed = Value<Unit<1,0,-1>>; // meters/second type
using Acceleration = Value<Unit<1,0,-2>>; // meters/second/second type

✅  2019/10/20 17:57, kt          #6 

Ну, и хорошо: есть понимание, что не все абстрактные типы одинаково полезны. Однако, с моей точки зрения, последний шаг так и не сделан. От "старых" представлений типов так и не отказались, т.е. обязательно нужно обозначить "Speed", "Acceleration" и т.д. Почему нельзя принять, что тип — это просто и именно [m/c], и тогда не нужно вводить все эти бесконечные импульсы, моменты инерции и гравитационные потенциалы.

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

✅  2019/10/28 23:55, Автор сайта          #7 

kt: ответственный секретарь редакционной коллегии журнала "Программирование"

Однажды один мой хороший знакомый как-то решил изучить программирование. Был бухгалтером, но, как говорится, «а мне летать охота». Но как изучить это самое программирование? Он взял и выписал журнал с таким названием. Потом он долго плевался, и годовая подписка журнала досталась мне.

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

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

У Дмитрия Юрьевича решение более элегантное. Этот аргумент оказался решающий, когда я принимал решение о размещении статей Дмитрия Юрьевича на этом сайте.

✅  2021/01/09 01:35, Visko          #8 

На первой же картинке во введении типы действительно не равны. Перепутаны fixed и float.
Интересно увидеть вывод компилятора при совпадении описаний.

✅  2021/01/09 18:08, kt          #9 

Просто перепишет 6 байт из одного участка памяти в другой

✅  2021/01/23 11:35, Неслучайный читатель          #10 

Математическая ошибка, которая заставила NASA окончательно пересмотреть систему мер, используемых в космических расчетах. Речь идёт о миссии Mars Climate Orbiter' 99. Космический аппарат был запущен в декабре 1998 года и прибыл к Марсу через 9 месяцев. За всё это время неисправностей и сбоев не произошло. 23 сентября спутник должен был выдать тормозной импульс и выйти на высокоэллиптическую орбиту. Но через 5 минут связь со спутником пропала навсегда. Внутреннее расследование NASA выявило, что компания Lockheed Martin, разработавшая и построившая аппарат, использовала британскую систему мер и весов. В британской системе за единицу момента силы принята величина фунт-сила, равная 0,113 традиционно используемой в системе СИ единицы Ньютон-метр. Инженеры Лаборатории реактивного движения использовали цифры Lockheed Martin, будучи абсолютно убежденными, что значения переведены в метрическую систему. Как результат, показатели отличались от расчетных в 8-9 раз (примерно 1/0,113), а спутник вместо орбиты высотой в 226 км вышел на орбиту 56 км и добросовестно сгорел в плотных слоях атмосферы

А ведь если б NASА и Lockheed Martin использовали описываемую здесь фичу, то и космический зонд был бы цел, и переходить на систему Си не потребовалось бы.

✅  2023/03/06 11:32, kiv(jobless)          #11 

Ещё один вариант в развитие понятия Тип
http://pl-euphoria.narod.ru/RapidEuphoria/russian/refman_2r.htm#43

✅  2023/03/09 13:13, void          #12 

Да уж, интересный этот язык Euphoria.

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

Автор сайта

✅  2023/03/09 19:13, kiv(jobless)          #13 

Я упомянул именно приём с контролем типов, а обсуждения Радостного программирования нужно переносить в другое место. Игорь Качан перевёл «эйфория» именно как радость.

✅  2023/03/10 00:55, MihalNik          #14 

Да уж, интересный этот язык Euphoria.
0. Есть несколько версий: актуальная OpenEuphoria, Phix, но есть и более ранние Euphoria, RapidEuphoria.
1. Была версия с русскими ключевыми словами и поддержкой кириллических идентификаторов

void, если что, на лисофоруме (plana.mybb.ru) руководство считает, что писать надо больше.

✅  2023/03/10 02:07, void          #15 

Я упомянул именно приём с контролем типов

Пример
  type hour(integer x)
return x >= 0 and x <= 23
end type

hour h1, h2

h1 = 10 -- ok
h2 = 25 -- ОШИБКА! Программа прерывается с сообщением
Напоминает "ограничения и подтипы" в Аде: range, subtype отсюда https://www.ada-ru.org/sssw/chapter_02

C той разницей, что Ада — язык системный и компилируемый, с полиморфизмом уровня пакетов, а "радость" — язык интерпретируемый и наполовину прикладной, наполовину достаточно системный и
всё ещё простой и наглядный.

а обсуждения Радостного программирования нужно переносить в другое место

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

✅  2023/03/10 02:17, void          #16 

Напоминает "ограничения и подтипы" в Аде: range, subtype отсюда https://www.ada-ru.org/sssw/chapter_02

Или даже буквально
subtype Hour is Integer  with Dynamic_Predicate => ... 
— аспекты в Ada 2012. Собственно, по той статье видно куда всё развивается в Ada 2012, 2020, SPARK — в сторону повышения степени формальной верификации и контрактного программирования (из "Design By Contract" в рантайме к доказательному программированию в SPARK в компайл-тайме).

✅  2023/03/17 23:27, Лавлинский Г.Ф.          #17 

Если сравнить типизацию, которая здесь описана, с традиционный типизацией, то её можно назвать типизацией высокого уровня. Традиционная типизация — она низкого уровня, её задача — разобраться с машинным представлением данных в памяти. Чтобы к целым числам применять целочисленное деление, а не деление для плавающих. А тут — типизация более высокого порядка, машинно-независимая, она апеллирует к назначению данных.

У меня вопрос по созданию новых типов высокого уровня. С инженерными задачами понятно, для них есть предопределённые «физические» типы. А как, допустим, создать «финансово-коммерческие» типы? Чтобы расценки за труд (рубли в час) умножить на время и вычислить начисленную зарплату. Чтобы коробки состояли из упаковок, ящики — из коробок, контейнеры — из ящиков. Чтобы зная стоимость килограмма получить цену после взвешивания. Есть способ расширения системы единиц измерения?

✅  2023/03/18 11:36, kt          #18 

На мой взгляд, для подобных задач подход "физических" типов не подходит. Здесь нужно применять такие "финансовые" типы не к данным типа Float, а к данным типа Decimal (в смысле этого типа в PL/1). А масштабные коэффициенты должны быть переменными, а не константами как у "физических" типов. Т.е. нужна другая реализация, а не расширение.

✅  2023/03/20 11:19, Автор сайта          #19 

Если рассуждать в терминах «типизация высокого уровня» и «типизация низкого уровня» из комментария выше (удачное предложение, мне кажется), то типы данных Float и Decimal — это типизация низкого уровня. А вопрос задавали про типы высокого уровня. Понятно, что предопределённого типа «рубли» нет. Хоть в представлении Float, хоть в представлении Decimal. Но как добавить этот тип? Я так понял, что никак.

Помню, в Клиппере было ООП, но своеобразное: можно создавать объекты классов, написанных разработчиками Клиппера. Но нельзя создавать новые классы. То есть ООП было нерасширяемое. В чём-то напоминает ситуацию.

✅  2023/03/20 11:41, kt          #20 

Я имел ввиду тип decimal вместо float для точных экономических расчетов (без округлений) для чего, собственно говоря, тип decimal и был введен. А переменные масштабных коэффициентов вместо констант — это, например, текущий курс валют. Т.е. экономические задачи и физические — разные направления.

✅  2023/03/20 12:09, Автор сайта          #21 

Тип double float в финансовых задачах используется повсеместно. Бывают неприятности, когда концы с концами не сходятся на копейки. Но мыши колются, но всё равно едят кактус.

Вопрос-то в другом. Как можно ли записать так:
 ставка почасовой оплаты = 300 [руб/час]
отработанных часов за месяц = 160 [час]
начисленная зарплата = ставка почасовой оплаты *
отработанных часов за месяц
и получаем рубли?

✅  2023/03/20 13:02, kt          #22 

Описанная реализация типов основана на (продуманной) международной системе СИ, на объективно существующей совокупности физических величин. И её нельзя расширить вне СИ. Если придумать другую систему, например, из человеков, часов и рублей, то можно похожим образом встроить её в транслятор. Но это будет другая система, не из 9 базовых величин и другой транслятор. Точно так же нельзя просто взять и расширить язык программирования ещё одним элементарным типом, только комбинацией из существующих. Поэтому никак не получатся рубли из "физических" типов.

✅  2023/03/20 17:30, Лавлинский Г.Ф.          #23 

Значит тому, кто тут придумывает языки программирования, будет чем заняться.

✅  2023/07/15 21:08, kt          #24 

Наконец появились другие реализации:

https://habr.com/ru/articles/748022/
https://habr.com/ru/articles/748248/

На мой, субъективный и заинтересованный взгляд, не очень удобно и продумано.

✅  2023/07/17 13:21, Автор сайта          #25 

Читаю комментарий:

Ну и как физик-теоретик по образованию, таки предпочитаю CGS, где, например, вязкость имеет размерность в пуазах/poise. Да даже в СИ — в паскалях x секунды. И таких даже не внесистемных единиц в физике — миллионы. Они реализованы в данной библиотеке? Всякие парсеки, meV, keV, MeV, GeV, TeV, PeV and EeV и пр.? Ну и как припрет решать большую систему линейных уравнений с помощью GMRES, так пока от размерностей не избавитесь, фиг какой прекондициондер вам поможет.

Комментарий автора статей:

В библиотеке имплементированы все базовые и производные единицы системы СИ и префиксы к ним степеней от -30 до +30. Кроме того, из имеющихся единиц можно строить новые или создавать свои, совсем новые.

Выше вы отвечали на вопрос, что у Вас в PL/1 нет возможности создавать новые единицы измерения.

На мой, субъективный и заинтересованный взгляд, не очень удобно и продумано.

Мне, чтобы иметь свой субъективный и не заинтересованный взгляд, надо пробовать и то и другое. Хотя синтаксис в Котлине вроде бы лаконичнее: точка, а не квадратные скобки. Но единицы измерения — латиницей, без вариантов русификации.
val s = 4.m * 4.3.m
val h = 32.l/s

✅  2023/07/17 20:12, kt          #26 

Тут все зависит от того, что понимать под "новыми единицами измерения". Скорость судна в узлах, это новая единица? Она основана на СИ и может быть создана, а, например, человеко-дни — нет.

Можно придумать свою систему взаимосвязанных типов. Но тогда причем тут СИ? СИ — законченная система и в этом её преимущество, на мой взгляд. В обеих заметках на хабре речь идет именно о СИ. Тогда какие новые единицы могут быть у закрытой системы?

✅  2023/07/17 22:29, Неслучайный читатель          #27 

Всякие парсеки, meV, keV, MeV, GeV, TeV, PeV and EeV и пр.

Парсеки приводятся к метрам, MeV и прочие однокоренные — это, по-видимому (мега)электрон вольт. Это приводится к джоулям. Какой-нибудь расход топлива из расчёта литры на 100 км тоже приводится к единицам измерения СИ.

СИ — законченная система . . . какие новые единицы могут быть у закрытой системы?

Почему закрытая? Вроде бы не все физические законы открыты. Есть другие, не физические единицы измерения. Например, рубли переводятся в доллары и обратно с каким-то коэффициентом. Или пишут, к примеру, что на первый компилятор Фортрана было потрачено 17 человеко-лет. Но ведь в СИ нет таких единиц измерения. Как говорила Фаина Раневская: «*опа есть, а слова нет».

Если в Котлине система единиц измерения расширяема, то это даст те же преимущества, что и для физических единиц измерения из СИ.

✅  2023/07/18 06:01, kt          #28 

Почему закрытая?

Потому, что все удалось свести к 7 независимым величинам, определяющим физическую картину мира. Найдете новую независимую величину — милости просим в Нобелевский комитет за законной премией по физике.

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

Как говорил О.Бендер Балаганову "это хрустальная мечта моего детства. Не касайтесь её своими грязными лапами". Не называйте это "расширенной СИ". Объективно её нет и быть не может. Не получается у меня достучаться до понимания. Точно так же в дискуссии о финансовых расчетах каждый новый участник радостно сообщает: "надо все хранить в целых копейках и проблема решена". Не решена и проблема не в копейках.

✅  2023/07/18 17:19, Неслучайный читатель          #29 

всё удалось свести к 7 независимым величинам, определяющим физическую картину мира.

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

Сейчас физики изучают тёмную материю. Когда наступит относительная ясность, то базис физики может оказаться не 7-мерным, а 8 и более.

Система СИ закрыта по определению.

Это либо отрицает возможность открытия новых физических законов, либо забвение СИ в этом случае.

Можно ввести любую систему типов, но тогда это не СИ.

Конечно. Ведь СИ — это физика. Но есть другие науки. У них другой понятийный аппарат. И нередко единицы измерения в них нельзя свести к физическим. Можно, конечно, в человеко-часах человека заменить на килограммы (ведь у каждого человека есть масса!), но если человеческий интеллект мерить килограммами, то это несуразица. Вот и получается, что измерения проводятся, единицы измерения существуют, но в системе СИ их нет. Примерно как у Раневской.

✅  2023/07/18 19:03, kt          #30 

измерения проводятся, единицы измерения существуют, но в системе СИ их нет.

"Это же квартет! — Ну и что, а у нас будет большой, расширенный квартет..." (с) "Карнавальная ночь"

Физики, конечно, изучают темную материю. Но есть подозрение, что эта материя — флогистон 21 века.

Добавить свой отзыв

Написать автору можно на электронную почту
mail(аt)compiler.su

Авторизация

Регистрация

Выслать пароль

Карта сайта


Содержание

Каким должен быть язык программирования?

Анализ и критика

Описание языка

Компилятор

Отечественные разработки

Cтатьи на компьютерные темы

●  О превращении кибернетики в шаманство

●  Про лебедей, раков и щук

●  О замысле и воплощении

●  О русском ассемблере

●  Арифметика синтаксиса-3

●  Концепция владения в Rust на примерах

●●  Концепция владения в Rust на примерах, часть 2

●●  Концепция владения в Rust на примерах, часть 3

●  Суть побочных эффектов в чисто функциональных языках

●  О неулучшаемой архитектуре процессоров

●  Двадцать тысяч строк кода, которые потрясут мир?

●  Почему владение/заимствование в Rust такое сложное?

●  Масштабируемые архитектуры программ

●  О создании языков

●●  Джоэл Спольски о функциональном программировании

●  Почему Хаскелл так мало используется в отрасли?

●  Программирование исчезнет. Будет дрессировка нейронных сетей

●  О глупости «программирования на естественном языке»

●  Десятка худших фич C#

●  Бесплатный софт в мышеловке

●  Исповедь правового нигилиста

●  ЕС ЭВМ — это измена, трусость и обман?

●  Русской операционной системой должна стать ReactOS

●  Почему обречён язык Форт

●  Программирование без программистов — это медицина без врачей

●  Электроника без электронщиков

●  Программисты-профессионалы и программирующие инженеры

●  Статьи Дмитрия Караваева

●●  Идеальный транслятор

●●  В защиту PL/1

●●  К вопросу о совершенствовании языка программирования

●●  Опыт самостоятельного развития средства программирования в РКК «Энергия»

●●  О реализации метода оптимизации при компиляции

●●  О реализации метода распределения регистров при компиляции

●●  О распределении памяти при выполнении теста Кнута

●●  Опыты со стеком или «чемпионат по выполнению теста Кнута»

●●  О размещении переменных в стеке

●●  Сколько проходов должно быть у транслятора?

●●  Чтение лексем

●●  Экстракоды при синтезе программ

●●  Об исключенных командах или за что «списали» инструкцию INTO?

●●  Типы в инженерных задачах

●●  Непрерывное компилирование

●●  Об одной реализации специализированных операторов ввода-вывода

●●  Особенности реализации структурной обработки исключений в Win64

●●  О русском языке в программировании

●●  Формула расчета точности для умножения

●●  Права доступа к переменным

●●  Заметки о выходе из функции без значения и зеркальности get и put

●●  Модификация исполняемого кода как способ реализации массивов с изменяемыми границами

●●  Ошибка при отсутствии выполняемых действий

●●  О PL/1 и почему в нём не зарезервированы ключевые слова

●●  Не поминайте всуе PL/1

●●  Скорость в попугаях

●●  Крах операции «Инкогнито»

●●  Предопределённый результат

●●  Поддержка профилирования кода программы на низком уровне

●●  К вопросу о парадигмах

●  Следующие 7000 языков программирования

●●  Что нового с 1966 года?

●●  Наблюдаемая эволюция языка программирования

●●  Ряд важных языков в 2017 году

●●  Слоны в комнате

●●  Следующие 7000 языков программирования: заключение

Компьютерный юмор

Новости и прочее




Последние отзывы

2024/12/07 20:54 ••• Клихальт
Переключатель

2024/12/06 18:44 ••• Анкнав
Русский язык и программирование

2024/12/01 00:00 ••• alextretyak
Продолжение цикла и выход из него

2024/11/29 23:08 ••• Вежливый Лис
О русском ассемблере

2024/11/26 23:53 ••• Бурановский дедушка
ЕС ЭВМ — это измена, трусость и обман?

2024/11/25 18:31 ••• Деньги на WWWетер
Ресурсы, посвящённые созданию языков программирования и компиляторов

2024/11/12 20:24 ••• Вежливый Лис
Правила языка: строки, комментарии

2024/11/12 13:10 ••• Вежливый Лис
Новости и прочее

2024/11/12 00:32 ••• Автор сайта
Оценка надёжности функции с несколькими реализациями

2024/11/06 02:50 ••• Иван
Энтузиасты-разработчики компиляторов и их проекты

2024/11/05 23:51 ••• Борис К.
Изменение приоритетов операций

2024/11/05 23:38 ••• Борис К.
Шестнадцатиричные и двоичные константы

2024/11/01 12:11 ••• ИванАс
Русской операционной системой должна стать ReactOS