ПО, ЭВМ и АСУ из Таможенного Союза

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » ПО, ЭВМ и АСУ из Таможенного Союза » Рефал » Арифметика


Арифметика

Сообщений 1 страница 13 из 13

1

С.Т. написал(а):

Полагаю, аналоги указанных команд процессора не имеют смысла в РЕФАЛ.

Звучит так, будто в нем нельзя складывать или именовать значения. В нем арифметика есть?

Отредактировано MihalNik (2021-04-16 18:22:10)

0

2

Целочисленная арифметика в Рефале является точной.

4.2. Встроенные функции арифметики. Некоторые функции существуют в Рефал-машине изначально – они называются встроенными.
Все встроенные функции арифметики целых чисел (
сложение – Add (или + ),
вычитание – Sub (или - ),
умножение – Mul (или * ),
деление – Div (или / ),
деление с остатком – Divmod,
остаток от деления – Mod,
сравнение – Compare
) логически имеют два аргумента, первый из которых заключён в структурные
скобки. Например,
<Add (1 0) 1> = 1 1
Результат деления с остатком есть пара:
<Divmod (e.n) e.m> = (e.q) e.r
где e.n = e.q * e.m + e.r , 0 6 | e.r | < | e.m | и знак остатка e.r совпадает со знаком делимого e.n .
Функция сравнения двух целых чисел Compare возвращает: ’+’ , если первое
больше второго; ’-’ , если первое меньше второго, и ’0’ , если числа равны.
В том случае, когда не возникает неоднозначности, структурные скобки, заключающие первый аргумент встроенных функций арифметики, можно опускать.

Отредактировано Лис (2021-04-16 18:39:58)

0

3

Лис написал(а):

Например,
<Add (1 0) 1> = 1 1

Примеры должны быть в понятном читателю виде, чтобы не возникало идиотских вопросов.
Это вот равносильно "10+1 = 11"?
А как сложить абстракные длину и ширину, помножить сумму на 2 и обозвать периметром?

Отредактировано MihalNik (2021-04-16 19:45:14)

0

4

MihalNik написал(а):

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

Совершенно верно. Не всех ведь удивляет отсутствие циклов, когда есть рекурсия.

MihalNik написал(а):

В нем арифметика есть?

Нормальные алгорифмы Маркова позволяют формализовать произвольный алгоритм без арифметических операций. На уровне языка РЕФАЛ арифметика не определена. Сложение реализовано как функция (т.е. уровень библиотеки).

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

MihalNik написал(а):

А как сложить абстракные длину и ширину, помножить сумму на 2 и обозвать периметром?

Определить функцию:

Код:
* в РЕФАЛ-5 вызов функции заключается в угловые скобки, аргументы следуют за её именем.
Perimeter {
  s.Length s.Width = <Mul <Add s.Length s.Width> * 2>;

* возможно специализировать для квадрата
*  s.SquareSide = <Add s.SquareSide * 4>;
}

* эквивалентный вариант (Refal-05 не поддерживает)
Perimeter {
  s.Length s.Width = <* <+ s.Length s.Width> * 2>;
}

// диалект с произвольным порядком в вычислительных скобках
периметр ?длина ?ширина = <<?длина + ?ширина> * 2>;

Отредактировано С.Т. (2021-04-17 13:26:24)

0

5

Я ничего не понял.

Как мне и советовали, всё что написано латиницей я пропустил.
Остался фрагмент кода:

// диалект с произвольным порядком в вычислительных скобках
периметр ?длина ?ширина = <<?длина + ?ширина> * 2>;

Здесь мне не ясно:
1) что такое "произвольный порядок"
2) что такое "вычислительные скобки"
3) а где, собственно, объявление функции
4) какой именно диалект имеется в виду, и как его устанавливать

Гипотетически, лет через пять, когда ответы на все эти вопросы перепишут из руководств на форум, станет понятнее.
Но пока непонятно.

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

И где они, где фигурные скобки?

Отредактировано Лис (2021-04-18 06:04:15)

0

6

Лис написал(а):

что такое "вычислительные скобки"

Цитирую РЕФАЛ-5 Руководство по программированию и справочник Турчин В.Ф., стр. 10:

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

<имя-функции аргумент>

где имя-функции является либо идентификатором, либо одним из четырёх знаков арифметических
операций (+, -, *, и /); а аргумент является общим РЕФАЛ-выражением. Таким образом,
вычислительные скобки могут быть вложенными.

Лис написал(а):

что такое "произвольный порядок"

Продолжаю цитату:

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

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

Лис написал(а):

а где, собственно, объявление функции

Цитирую вышеуказанную страницу:

"Функциональное определение имеет одну из следующих форм:

имя-функции { блок }"

Объявления функций в РЕФАЛ нужны только в случае, если их определение приведено во внешнем файле (модуле).

Лис написал(а):

какой именно диалект имеется в виду, и как его устанавливать

Если я являюсь автором реализаци одного из диалектов, по умолчанию я говорю именно о нём. Вариант установки описан здесь.

Лис написал(а):

И где они, где фигурные скобки?

Цитирую "Основные отличия":

"Поддержаны функции из одного предложения, без блока { }."

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

Отредактировано С.Т. (2021-04-18 09:07:10)

0

7

С.Т. написал(а):

позволяет располагать имя функции после её аргументов.

Но в примере имя функции располагается не после аргументов, а между ними.
Можно ли, например, написать

объём ?длина ?ширина ?высота  ?запас = < ?запас + ?длина * ?ширина * ?высота > ;

или надо обязательно

объём ?длина ?ширина ?высота  ?запас  = <?запас+<<?длина*?ширина>*?высота>> ;

Начинающиеся с $ директивы не поддерживаются.

Т.е. весь код всегда должен быть в одном файле?

следует импортировать модуль явно. Для чего указывается имя модуля, завершаемое двоеточием:
    Модуль: функция1 функция2;

Вроде в каком-то из руководств это делалось как раз при помощи $-директив...

Отредактировано Лис (2021-04-18 13:44:16)

0

8

Лис написал(а):

Но в примере имя функции располагается не после аргументов, а между ними.

Так тоже возможно. Потому порядок назван произвольным. Здесь надо понимать, что если после (правее) идентификатора функции встречается идентификатор другой функции, то второй является аргументом для первой (реализация которой может вызвать вторую по идентификатору при помощи функции Mu).

Лис написал(а):

Можно ли, например, написать

объём ?длина ?ширина ?высота  ?запас = < ?запас + ?длина * ?ширина * ?высота > ;

или надо обязательно

объём ?длина ?ширина ?высота  ?запас  = <?запас+<<?длина*?ширина>*?высота>> ;

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

Второй же вариант станет корректен, если отделить идентификаторы функций пробелами. *?высота воспринимается как один идентификатор. Sum-1 является допустимым именем функции и в реализации Турчина. У меня можно задать функцию с именем -1, -- и т.п.

Лис написал(а):

Т.е. весь код всегда должен быть в одном файле?

Про это сказано в О реализации:

Для вызова функций, реализованных в другой единице трансляции (модуле), следует импортировать модуль явно. Для чего указывается имя модуля, завершаемое двоеточием:

Код:
    Модуль: функция1 функция2;

РЕФАЛ-машина ищет реализацию модуля в файлах Модуль.реф и Модуль.ref. Указанные в команде импорта идентификаторы вносится в текущую область пространства имён. Остальные идентификаторы модуля так же доступны, если их имя предварительно квалифицировать именем модуля:

Код:
    * Импортируем идентификаторы тест1 и тест2 из файла "Модуль1.реф"
    Модуль1: тест1 тест2;
    go = <тест1> <тест2>
       * Вызов по полному имени.
           <Модуль1 тест3>;

Вот пример изменений исходников компилятора Refal-05:

Код:
diff --git a/src/R05-CompilerUtils.ref b/src/R05-CompilerUtils.ref
index 0bcd09c..514de7f 100644
--- a/src/R05-CompilerUtils.ref
+++ b/src/R05-CompilerUtils.ref
@@ -1,20 +1,20 @@
-*$FROM LibraryEx
-$EXTERN Trim, Map;
+LibraryEx: Trim Map ExistFile;

Т.е. удаляются
*$FROM LibraryEx
$EXTERN Trim, Map;

и добавляется
LibraryEx: Trim Map ExistFile;

---
*) Не вижу технических ограничений реализовать функцию +, которая будет считать арифметические выражения привычного со школы вида и поймёт первый вариант. Однако не ясно, как быть с круглыми скобками в выражениях. С точки зрения языка 1 (или другое значение переменной ?запас) -- это символ-макроцифра, а + -- это символ-идентификатор (функции). У Турчина минус перед числом хранился и рассматривался как отдельный символ. Круглые скобки в РЕФАЛ группируют символы. Запись (+ + +) валидна на этапе трансляции. Вычислительные (угловые) скобки явно указывают приоритет операций, тем самым сходны с математическими круглыми (но, в отличие от последних, не могут быть опущены). Запись <0 1 2>  приведёт к ошибке до исполнения. С одной стороны круглые скобки мешают пониманию сути языка (обработчика последовательностей символов), с другой - переносят часть ошибок на время исполнения. В общем, есть ряд вопросов к "стандартной" библиотеке. По-хорошему, следует её основательно переработать. Касательно арифметики, я пока склоняюсь к варианту, когда для сложных арифметических выражений применяется специальная функция (в первом приближении назовём её "калькулятор").

Отредактировано С.Т. (2021-04-19 11:48:48)

0

9

С.Т. написал(а):

удаляются
*$FROM LibraryEx
$EXTERN Trim, Map;

и добавляется
LibraryEx: Trim Map ExistFile;

Т.е. ломается совместимость с документацией и другими реализациями. А зачем - непонятно.

Почему бы тогда не поменять угловые и квадратные скобки по смыслу местами.
Ну в математике же
{множество} - множество элементов
<набор> - последовательность элементов с некоторым порядком
да и круглые скобки в других местах связываются с вызовом функции.

Отредактировано Лис (2021-04-19 12:41:36)

0

10

Лис написал(а):

Т.е. ломается совместимость с документацией и другими реализациями. А зачем - непонятно.

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

Кроме того, в техническом плане, Refal PZ является компилятором. Имена модулей передаются ему в параметрах рядом с именем основной программы и в её исходном тексте не указываются (Refal-05 обходит это трюком с записью директивы *$FROM LibraryEx после звёздочки, что является комментарием в Refal-5 PZ). В интерпретаторе подобный подход вызывает сложности. Параметры командной строки, как правило, требуется передать исполняемой программе на РЕФАЛ.

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

Лис написал(а):

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

Во-первых, квадратные скобки [] есть Рефал-5λ, в Рефал-5 их нет. Во-вторых, предлагаемая замена не равноценна. Предлагается потерять совместимость определений функций Рефал-5, тогда как в данном случае нарушена лишь совместимость формата описания связывания внешних идентификаторов, при этом добавлена поддержка пространств имён. Требуемые изменения в исходных текстах минимальны.

0

11

С.Т. написал(а):

квадратные скобки [] есть Рефал-5λ

Про квадратные скобки я вообще не знал. Когда я писал, я хотел написать "угловые и круглые", но ошибся.

С.Т. написал(а):

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

Можно было русскими словами написать, но раз уж в целом синтаксис изменён, то это не важно.

Текст про сравнение реализаций интересный. Когда читал его думал о сравнении рефалов с Nemerle.

0

12

Лис написал(а):

Когда я писал, я хотел написать "угловые и круглые", но ошибся.

Если понимать, что РЕФАЛ является языком вычислений над символами, то есть абстракцией высшего по сравнению с арифметикой порядка, тогда оказывается, что круглые скобки на своём месте.

0

13

Пример в тему:

Код:
*
* Реализует сложение и умножение целых неотрицательных чисел с произвольным числом разрядов
* для произвольных основания системы счисления и набора символов-цифр.
*
* Автор: Даниил Исакевич.
*
* https://forum.altlinux.org/index.php?topic=44627.msg373938#msg373938
*

начало =
    <напечатать "Таблица умножения">
    <таблицаумножения>
    <напечатать "\n" "Таблица сложения">
    <таблицасложения>
    <напечатать>
    <напечатать "I8!=" <убрать-скобки <факториал ("I8")>>>
    <напечатать "IZ2!=" <убрать-скобки <факториал ("IZ2")>>>
    <напечатать>
    <сложитьчисла
        <перемножитьчисла ("I23456789") ("98765432I")>
        ("I2345432I")>;
* Поле зрения по завершении: (I2I93263I236Z8959Z)

*Задаётся нужный набор цифр-символов,
*основание системы счисление - длина этого набора:
*всецифры = "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F";
всецифры = "Z" "I" "2" "3" "4" "5" "6" "7" "8" "9";
* для разнообразия нуль обозначен Z (zero), единица I

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


* Вычисление факториала
факториал {
    (.разряды) = <факториал (.разряды) <всецифры>>;
    (?цифрануль) ?цифрануль ?цифраодин .остальные = (?цифраодин);
    (.разряды) .всецифры =
        <перемножитьчисла
            (.разряды)
            <факториал <предыдущеечисло (.разряды)>>>;
}


* Вывод таблицы сложения и таблицы умножения

таблицаумножения = <вывести-таблицу "*">;
таблицасложения = <вывести-таблицу "+">;

вывести-таблицу {
    ?знак =
        <напечатать <с-табуляцией ?знак <всецифры>>>
        <вывести-таблицу ?знак (<всецифры>) (<всецифры>)>;
    ?знак () (.всецифры) = ;
    ?знак (?цифра .остальные) (.всецифры) =
        <напечатать
            ?цифра
            <строка-таблицы ?знак ?цифра (.всецифры)>>
        <вывести-таблицу ?знак (.остальные) (.всецифры)>;
}

строка-таблицы {
    ?знак ?цифра1 () = ;
    ?знак ?цифра1 (?цифра2 .остальные) =
        "\t"
        <убрать-скобки <вычислить ?знак (?цифра1) (?цифра2)>>
        <строка-таблицы ?знак ?цифра1 (.остальные)>; 
}

вычислить {
    "+" (.число1) (.число2) = <сложитьчисла (.число1) (.число2)>;
    "*" (.число1) (.число2) = <перемножитьчисла (.число1) (.число2)>;
}


* Функции декремента, инкремента, сложения, умножения

перемножитьчисла {
    (.разряды1) () = ();
    (.разряды1) (.старшиеразряды2 ?младшийразряд2) =
        <сложитьчисла
            <приписать-цифру
                <перемножитьчисла (.разряды1) (.старшиеразряды2)>
                <нуль>>
            <умножитьчислонацифру (.разряды1) ?младшийразряд2>>;
}

умножитьчислонацифру {
    (.разряды) ?цифра = <умножитьчислонацифру (.разряды) ?цифра <всецифры>>;
    (.разряды) ?цифрануль ?цифрануль .остальные = (?цифрануль);
    (.разряды) ?цифраодин ?цифрануль ?цифраодин .остальные = (.разряды);
    (.разряды) ?цифра .всецифры =
        <сложитьчисла
            (.разряды)
            <умножитьчислонацифру
                (.разряды)
                <предыдущаяцифра ?цифра>>>;
}

сложитьчисла {
    (.разряды1) (.разряды2) = <сложитьчисла (.разряды1) (.разряды2) <всецифры>>;
    (.старшиеразряды1 ?младшийразряд1) (.старшиеразряды2 ?цифрануль)
    ?цифрануль .остальные =
        <приписать-цифру
            <сложитьчисла
                (.старшиеразряды1)
                (.старшиеразряды2)>
            ?младшийразряд1>;
    (.старшиеразряды1 ?цифрануль) (.старшиеразряды2 ?младшийразряд2)
    ?цифрануль .остальные =
        <сложитьчисла
            (.старшиеразряды2 ?младшийразряд2)
            (.старшиеразряды1 ?цифрануль)>;
    () (.разряды) .всецифры = (.разряды);
    (.разряды) () .всецифры = (.разряды);
    (.старшиеразряды1 ?младшийразряд1) (.старшиеразряды2 ?младшийразряд2)
    .всецифры =
        <сложитьчисла
            <следующеечисло (.старшиеразряды1 ?младшийразряд1)>
            (.старшиеразряды2 <предыдущаяцифра ?младшийразряд2>)>;
}

следующеечисло {
    () = (<один>);
    (.разряды) = <следующеечисло (.разряды) (<всецифры>)>;
    (.старшиеразряды ?младшийразряд) (.до ?младшийразряд ?следующ .после) =
        (.старшиеразряды ?следующ);
    (.старшиеразряды ?младшийразряд) (?перваяцифра .между ?младшийразряд) =
        <приписать-цифру
            <следующеечисло (.старшиеразряды)>
            ?перваяцифра>;
}

предыдущеечисло {
    (.разряды) = <предыдущеечисло (.разряды) <всецифры>>;
    (.старшиеразряды ?цифрануль) ?цифрануль .между ?последняяцифра =
        <приписать-цифру
            <убрать-ведущие-нули <предыдущеечисло (.старшиеразряды)>>
            ?последняяцифра>;
    (.старшиеразряды ?цифра) .до ?предыдущ ?цифра .после =
        (.старшиеразряды ?предыдущ);
}

убрать-ведущие-нули {
    (.разряды) = <убрать-ведущие-нули (.разряды) <всецифры>>;
    (?цифрануль .остальныеразряды) ?цифрануль .остальныецифры =
        <убрать-ведущие-нули (.остальныеразряды)>;
    (.разряды) .всецифры = (.разряды);
}

предыдущаяцифра {
    ?цифра = <предыдущаяцифра ?цифра <всецифры>>;
    ?цифра .до ?предыдущ ?цифра .после = ?предыдущ;
    ?цифра ?цифра .между ?последняя = ?последняя;
}

приписать-цифру {
    (.разряды) ?цифра = (.разряды ?цифра);
}

нуль {
    = <нуль <всецифры>>;
    ?цифрануль .остальные = ?цифрануль;
}

один {
    = <один <всецифры>>;
    ?цифрануль ?цифраодин .остальные = ?цифраодин;
}


* Функции для оформления

убрать-скобки {
    (.разряды) = .разряды;
}
с-табуляцией {
    = ;
    ?символ .прочие = ?символ "\t" <с-табуляцией .прочие>;
}
напечататьчисло {(.разряды) = <напечатать .разряды>;}
напечатать {.чтонибудь = <Prout .чтонибудь>;}
напечатать-промежуточный {.что-нибудь = <напечатать .что-нибудь> .что-нибудь;}

0


Вы здесь » ПО, ЭВМ и АСУ из Таможенного Союза » Рефал » Арифметика