Правила программирования расчетов

Текст конкретной программы начинается с пустой строки (для первой программы необязательно) и заканчивается пустой строкой. В тексте программы могут быть комментарии, которые пишутся обычным образом без знаков разметки. Однако операторы программы отмечаются так, что первым знаком, указывающим на оператор является символ #. Если нужно проводить вычисления, то после него ставится символ пробела и затем проводятся вычисления. Кроме того, программа понимает операторы простого цикла #rep и цикла по условию #case . О них будет сказано позднее. Программа может оперировать с переменными, имена которых состоят из одной буквы латинского алфавита. то есть a-z и A-Z. Большие и маленькие буквы означают разные переменные. Всего 52 переменных. Дополнительно переменные могут иметь имена, состоящие из одной буквы и одной цифры, то есть m1, N2 и так далее. Всего таких переменных 520. Также можно использовать элементы реального массива r(n), индекс массива может принимать значения от 1 до 19999. Индекс массива может содержать выражения, состоящие из чисел и переменных.

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

  # a=1; b=sin(a); c=b<2; r(5000)=a*b;

То есть два знака [# ] (пробел после решетки обязателен) открывает поле операторов присваивания с конструкцией <name>=<value>; причем пробелы между этими элементами могут быть в любом количестве, в том числе и отсутствовать. Можно все писать совсем без пробелов. Это поле заканчивается либо знаком [#], то есть началом новой команды, либо знаком [@]. Можно ставить комментарии специальной конструкции, но проще оборвать поле командой #% записать комментарий, а потом открыть новую команду. Команда #% ничего не делает и используется просто как ограничитель расчетов. Для выполнения вычислений есть все стандартные операции

     +  -  *  /  ^  (  )

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

    abs() == абсолютное значение
    sqr() == квадратный корень
    log() == натуральный логарифм
    exp() == экспонента
    sin() == синус
    ars() == арксинус
    cos() == косинус
    arc() == арккосинус
    tan() == тангенс
    art() == арктангенс
    rnd() == случайное значение
    int() == целая часть
    sfi() == синус интеграл Френеля int(0,x)dt*sin((pi/2)*t^2)
    cfi() == косинус интеграл Френеля int(0,x)dt*cos((pi/2)*t^2)
    bj0() == функция Бесселя J[0](x)
    bj1() == функция Бесселя J[1](x)

Аргумент у функций записывается в круглые скобки так же, как и индексы элементов массива. У функции rnd() аргумент не используется, но для соблюдения грамматики надо писать rnd(0). Функция int() получается отбрасыванием дробной части у числа независимо от знака. При этом положительное число становится меньше, а отрицательное -- больше. Для получения ближайшего целого к положительному числу к аргументу функции надо добавить 0.5, а к отрицательному -0.5. Числа можно писать в любом формате как с точкой, так и с запятой и в экспоненциальной форме как с [E] так и с [e]. Вот примеры правильной записи чисел:

      1,23 1.23 12,3E-1 0.123E1 123e-2

Но плюс к указанным добавлены две новые операции a<b и a>b . Они означают меньшее из двух и большее из двух. Обычно это делается функцией двух переменных, но в нашем случае нет функций двух переменных, а минимум и максимум реализован операцией. Например, a<1 означает [a], если [а] меньше единицы, и 1, если больше. Приоритет этих операций выше всех других, кроме скобок. То есть все сложные части этих операций обязательно должны быть в скобках.

В результате введения операций [<] и [>] оказалось возможным упразднить все так называемые условные операторы, оставив только блок из двух команд, реализующий ветвление вариантов и дополненный двойной проверкой условия. А именно, конструкцию

  #case N . . . #end 

где N есть аргумент команды #case. Аргумент может быть числом, переменной или элементом массива, а многоточием обозначены все другие команды данного варианта расчетов, которые выполняются лишь в том случае, если выполняется условие N=&. Команда #end ограничивает число операторов данного варианта и проводит дополнительный анализ условия, а & - это имя специальной переменной, которая наравне с другими переменными может участвовать в расчетах. Самой простой логической операцией, которую можно реализовать с помощью этой команды является ветвление. Допустим у нас есть несколько вариантов кода, из которых надо выполнить какой то один. Это делается набором команд

  # &=2;
  #case 1 . . . #end |   
  #case 2 . . . #end |   
  #case 3 . . . #end |   
  и так далее.

В написанном коде будет выполнен второй вариант. Достаточно поменять значение переменной [&], не трогая остальной код, и будет выполнен другой вариант. Но пара команд #case N ... #end является также и универсальным описанием цикла, то есть многократного повторения последовательности команд, которые будут стоять вместо многоточия. Дело в том, что условие N=& проверяется не только при выполнении открывающей команды #case но и при выполнении закрывающей команды #end. Если это условие снова выполняется, то все команды варианта (то есть то, что вместо многоточия) выполняются снова и так до бесконечности. При этом значение N (аргумент команды #case) уже изменить нельзя, аргументы считываются только один раз, но вот значение переменной & изменить можно и нужно. Чтобы облегчить запись такого изменения, конструкция #end | (с вертикальной чертой через пробел) сначала выполняет операцию &=12345;, а затем проверяет условие. Есть еще вариант #end (a), когда выполняется операция &=a; перед проверкой условия. Но этим вариантом я практически не пользуюсь. Хотя иногда он проще, чем определять переменную & повторно. Надо просто привыкнуть. У этой пары команд есть все таки и различие. Дело в том, что команда #case проверяет условие N=& на точных вещественных числах, а команда #end -- только на целых, то есть сравниваются лишь целые части обоих чисел. Вообще говоря, разумно все условия проверять на целых числах, так как в вещественных числах могут возникать ошибки округления. Но тем не менее, про эту особенность надо знать. Рассмотрим пример,

  # i=0; &=i; #case 0 . . . . # i=i+1; &=(5-i)<0; #end

Здесь многоточие выполнится для i=0,1,2,3,4,5 и затем цикл закончится и программа будет выполнять следующие команды. В такой конструкции #case работает как простой цикл. Но для удобства для этих целей есть и простая команда

  #rep N . . . #end

которая просто N раз повторяет многоточие. Команда #case реально позволяет выполнить или не выполнить что-то в зависимости от любого логического условия. Нужно только правильно определить переменную & используя операции [<] и [>] . То есть она одна заменяет и оператор if( ){ } и оператор while( ){ } и оператор switch( ){ } языка Java, а также аналогичные операторы других языков. И в то же время никаких ограничений на возможности программирования не накладывает.
Для тех, кто знаком с языками программирования, например, Java, я поясню аналогию. Например, код на Java

  if( a == 1 ){ что-то сделать }

может быть записан как

  # &=a; #case 1 что-то сделать #end |

Более сложный код

  if( a <= 1 && b >= 2 ){ что-то сделать }

может быть записан как

  # &=(a-1)>0+(2-b)>0; #case 0 что-то  сделать #end |

Другое условие

  (a <= 1 || b >= 2 )

эквивалентно

  # &=(a-1)>0*(2-b)>0; #case 0 ...

В принципе все условия оператора if( ){ } могут быть записаны как равенство нулю некоторого выражения. Команда #end | изменит & на значение 12345 и поэтому тело цикла будет выполнено только один раз. Чтобы получить форму while( ){ } нужно использовать чистую команду #end и вычислять переменную & еще раз внутри цикла. Форма switch( ){ } наиболее простая: определяете переменную & один раз и используете много команд #case ... #end | с разными значениями аргумента, как было показано выше.

Наконец последнее: как простые так и условные циклы могут быть вложены друг в друга с числом вложений до 25. То есть можно писать так

  # x=0; j=1; N=10; M=10;
  #rep N # y=0;
   #rep M # r(j)=x*y; y=y+1; j=j+1; #end # x=x+1;
  #end 

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

Для более удобной работы с массивом дополнительно существуют еще две простые команды. Первая из них

  #data N r(11) a b c*5 g ...

Имя этой команды (data) можно сократить до одной буквы, то есть писать #d . Она позволяет быстро определить значения элементов массива. Первый аргумент N определяет сколько элементов будет определено, второй указывает первый элемент массива для определения. Эта запись фактически задает первый индекс массива. Важно иметь в виду, что переменные тоже образуют массив, специальным образом упорядоченный, так что их тоже можно определять таким способом. А после идут значения, которые надо присвоить элементам массива. Это могут быть числа, переменные и элементы массива. Если после значения стоит *5, то это означает, что данное значение нужно взять 5 раз. Итак аргументы команды образуют следующую структуру: <число><начало массива><данные>. Но таких структур может быть сколько угодно, одна структура следует за другой. Окончание опять либо на знаке [#] либо на знаке [@] - все остальное трактуется как ошибка. Число N ограничено и не может быть больше 500.

Вторая команда

  #pas N r(11) r(25)

позволяет быстро присвоить значения одной совокупности элементов массива другой совокупности элементов массива, то есть, как говорят, переслать значения из одной части массива в другую часть. Первым указывается массив из которого пересылаются значения, вторым - куда пересылаются. В этой команде структура не повторяется. Надо снова писать имя команды. Число N не ограничено.

  Внимание! Сайт оптимизирован под браузер Google Chrome.