Лекция 2, где мы познакомимся с векторами и матрицами и научимся писать небольшие программки.
Сразу скажу, что массивов как таковых в PARI/GP нет. Функции одномерных массивов выполняют
векторы, а двумерных -
матрицы. А вот массивов размерности большей 2-х нет совсем, но они нам и не понадобятся.
Векторы создаются командой
vector, а матрицы командой
matrix, аргументом которых в простейшем случае является размерность. По умолчанию создаваемые векторы и матрицы заполняются нулями. Нумерация индексов в векторах и массивах всегда начинается с 1.
В этом примере мы создаем вектор
и матрицу
, меняем значения их элементов и печатаем измененные
и
:
Код:
? v=vector(10)
%1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
? v[1]=1
%2 = 1
? print(v)
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
? M=matrix(2,5)
%3 =
[0 0 0 0 0]
[0 0 0 0 0]
? M[3,4]=7
*** array index (3) out of allowed range [1-2].
? M[2,4]=7
%4 = 7
? print(M)
[0, 0, 0, 0, 0; 0, 0, 0, 7, 0]
Результат последней команды показывает как матрица записывается в строчном виде: перечисляются элементы каждой строки через запятую, а сами строки разделены точкой с запятой, и все это заключено в квадратные скобки. То есть, например, определить матрицу
можно так:
Код:
? [1,2;3,4]
%6 =
[1 2]
[3 4]
Важно заметить, что у
vector и
matrix есть варианты с функциональным заполнением создаваемых векторов/матриц:
vector( длина, индекс, функция_от_индекса ) и
matrix( число_строк, число_столбцов, индекс_по_строкам, индекс_по_столбцам, функция_от_индексов ):
Код:
? u = vector(5, i, i^2)
%7 = [1, 4, 9, 16, 25]
? K = matrix(3,5,i,j,i*j)
%8 =
[1 2 3 4 5]
[2 4 6 8 10]
[3 6 9 12 15]
В этом примере мы создали вектор, состоящий из квадратов чисел от 1 до 5, и матрицу, являюшуюся таблицей умножения размером
.
Попробуем их перемножить:
Код:
? K*u
*** _*_: impossible multiplication t_MAT * t_VEC.
Возникшая ошибка связана с тем, что векторы по умолчания являются вектор-строками, а умножать матрицу нам нужно на вектор-столбец. Не велика беда, нужно лишь транспонировать вектор u с помощью постфиксного оператора
~:
Код:
? K*u~
%9 = [225, 450, 675]~
Как видим, в результате получается опять же вектор-столбец, о чем говорит тильда в конце его строчной записи. То есть
[225, 450, 675] - это вектор-строка, а вот
[225, 450, 675]~ - это уже вектор столбец. Кстати, тильдой можно транспонировать и матрицы (хотя для этого же есть фунция
mattranspose):
Код:
? K~
%10 =
[1 2 3]
[2 4 6]
[3 6 9]
[4 8 12]
[5 10 15]
? K~ == mattranspose(K)
%11 = 1
Операция
== - это тестирование равенства, результатом является либо
0 (ложь), либо
1 (истина). Как видим, в этом примере результат
K~ совпадает с результатом
mattranspose(K).
Заметим, что набирать длинные команды в PARI/GP просто засчет автоматического донабора (пользователям консоли в линуксе эта возможность хорошо известна как bash autocomplete).
Например, вместо длинного mattranspose достаточно набрать matt и нажать кнопку
TAB - PARI/GP автоматически догадается, что вы хотите набрать mattranspose и сам донаберет оставшиеся символы. Если же вариантов донабора много, то после однократного нажатия
TAB ничего не произойдет, а вот если его нажать его во второй раз, то PARI/GP покажет все возможные варианты. Например, набрать mata и нажав
TAB два раза, вы увидите:
Код:
? mata
matadjoint matalgtobasis
Теперь набрав еще одну букву, скажем, d и нажав
TAB, вы получите слово matadjoint(), так как никаких неоднозначностей тут уже нет.
Если необходимо выполнить несколько команд в одной строке (или в теле цикла, например), то нужно их разделить точкой с запятой. То есть создать вектор u, матрицу K и перемножить их можно было в одну строку:
Код:
? u = vector(5, i, i^2); K = matrix(3,5,i,j,i*j); K*u~
%12 = [225, 450, 675]~
Или вот так можно напечатать все простые числа вида
, где
:
Код:
? for(n=150,300, t=n^2+1; if( isprime(t), print1(t,", ") ) )
22501, 24337, 25601, 28901, 30977, 32401, 33857, 41617, 42437, 44101, 50177, 52901, 55697, 57601, 62501, 65537, 67601, 69697, 72901, 78401, 80657, 90001,
Из этого примера мы узнаем о конструкции
if( условие, код_если_выполнено ), которая в более общем виде выглядит как
if( условие, код_если_выполнено, код_если_не_выполнено ), а также о функции
isprime(), которая тестирует целые числа на простоту. Она возвращает 1, если аргумент является простым числом, 0 в противном случае.
Кстати, точка с запятой может служить также для подавления вывода результата команды на экран. Сравните:
Код:
? x = 2+3
%13 = 5
? x = 2+3;
Команды абсолютно идентичные по действию, но результат первой печатается на экране, а второй - нет.
Ну и напоследок о том, как набирать многострочные команды - их нужно всего лишь заключить в { }. Если присутствует открывающаяся фигурная скобка, но еще нет закрывающейся, то PARI/GP не будет реагировать на нажатие
enter как сигнал к выполнению кода. Пример, который мы разбирали выше, но в многострочном варианте:
Код:
? { for(n=150,300,
t=n^2+1;
if( isprime(t), print1(t,", ") )
) }
22501, 24337, 25601, 28901, 30977, 32401, 33857, 41617, 42437, 44101, 50177, 52901, 55697, 57601, 62501, 65537, 67601, 69697, 72901, 78401, 80657, 90001,
На этом Лекцию 2 будем считать законченной. Вопросы?