TI-NSpire динамически создает переменные для векторного перекрестного произведения
Хорошо, я пытаюсь создать функцию перекрестного произведения в TI-NSpire, которая взяла n-1 векторов измерения n и взяла определитель матрицы следующим образом:
[[u_x,u_y,u_z,u_w],
[a_1,a_2,a_3,a_4],
[b_1,b_2,b_3,b_4],
[c_1,c_2,c_3,c_4]]
Верхний ряд - это единичные векторы, направленные в направлении осей. К сожалению, проблема в том, что, если я не передам калькулятору неопределенные переменные, поиск определителя этой матрицы приведет к ошибке, поскольку либо u_x, u_y... и т. Д. Являются векторами, а матрица не является надлежащей матрицей, либо векторы значения, и определитель приводит к единственному значению, а не к вектору. Однако я могу оставить неопределенные векторы единиц измерения и выполнить определитель, а затем определить переменные после завершения определения.
То, что у меня осталось, это либо ограничить себя максимальным размером вектора (не без оснований, но я бы предпочел не использовать это), либо динамически создать список из n неопределенных локальных переменных, которые я могу установить для единичных векторов после завершения вычислений.,
Мой вопрос: как можно выполнить второй вариант, если это вообще возможно?
отредактируйте код: (Примечание: в настоящее время используется список переменных, о котором я упоминал. К сожалению, проблема в этом заключается в ошибках "5→{a,b,c,d}[1,2]".)
Define LibPub cross_p(mat)=
Func
:Local i_,n_,unit_v,unit_list
:Local dim_v,num_v,len_v,new_v
:Local det_v
:[a,b,c,d,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z]→unit_list
:dim(mat)→dim_v
:dim_v[1]→num_v
:dim_v[2]→len_v
:newMat(len_v,len_v)→unit_v
:For n_,1,len_v
: 1→unit_v[n_,n_]
:EndFor
:If num_v=len_v-1 Then
: newMat(len_v,len_v)→new_v
: subMat(unit_list,1,1,1,len_v)→new_v[1]
: For i_,1,num_v
: mat[i_]→new_v[i_+1]
: EndFor
: det(new_v)→det_v
: For i_,1,len_v
: unit_v[i_]→unit_list[1,i_]
: EndFor
: Return det_v
:EndIf
:EndFunc
2 ответа
ОП здесь. Я чувствовал, что решение, которое я нашел, является подходящим для правильного ответа, а не простого обновления.
Define LibPub v_crossp(v_list)=
Func
:Local i,num_v,new_v,det_v,vec,v_coeff,n_coeff
:dim(v_list)[2]→num_v
:newMat(num_v,num_v)→new_v
:newList(num_v)→vec
:For i,1,num_v
:unit^(i-1)→new_v[1,num_v+1-i]
:EndFor
:For i,1,num_v-1
: v_list[i]→new_v[i+1]
:EndFor
:det(new_v)→det_v
:polyCoeffs(det_v,unit)→v_coeff
:dim(v_coeff)→n_coeff
:If n_coeff<num_v Then
: listoperations\reverselist(v_coeff)→v_coeff
: For i,1,n_coeff
: v_coeff[i]→vec[i]
: EndFor
: listoperations\reverselist(vec)→vec
: Return vec
:Else
: Return v_coeff
:EndIf
:Return new_v
:Return expand(det_v)
:EndFunc
Эта функция работает довольно хорошо, на самом деле. Функция reverselist() просто переворачивает список. Код прост.
Define LibPub reverselist(list)=
Func
:Local i,size,l_new
:size:=dim(list)
:l_new:=newList(size)
:For i,1,size
: list[i]→l_new[size+1-i]
:EndFor
:Return l_new
:EndFunc
Я также, кажется, наткнулся на некоторые векторы, где единственный вектор, перпендикулярный всем трем (<1,2,3,4>, <5,6,7,8>, <9,10,11,12>), является <0,0,0,0>. Однако, если бы кто-то мог это подтвердить, я был бы очень признателен.
Вся эта функция работает из-за того, как калькулятор обрабатывает полиномы. Таким образом, мои "единичные" векторы в функции равны 1, единице, единице ^2, единице ^3 и т. Д. Таким образом, как только он определит, коэффициенты переменной "единица" становятся компонентами вектора. Кроме того, в процессе тестирования я обнаружил, что если детерминант приводит к нулю, умноженному на ведущую степень многочлена (скажем, на единицу ^3), то вектор будет коротким компонентом (но если бы 0 был умножен на любое из более слабых условий, но не ведущей власти, не было никаких проблем). В случае, если определитель привел к 0, результатом был просто пустой список. Цикл if с вложенным циклом for заботится об этом, гарантируя, что каждый из компонентов находится в списке надлежащей длины (таким образом предотвращая путаницу и заставляя исполнителя выполнять дополнительную работу, чтобы вернуться к правильной длине списка) и что эти компоненты находятся в нужном месте.
Я уверен, что код можно улучшить и сделать быстрее, но я доволен результатом. Спасибо всем за помощь.
В NSpire элементы матрицы должны быть скалярами.
Это подразумевает две вещи:
1) `[i, j, k, l]` must be written `augment(i,augment(j,augment(k,l)))`
2) the output of det is a scalar
Последнее самое неприятное для вас. Это в основном означает, что вам нужно написать свою собственную версию det
если вы хотите использовать свой подход.
Теперь вторая часть вопроса заключается в том, как реализовать это для произвольных измерений. Грустная часть в том, что "язык программирования" в NSpire очень ограничен. Первая сложность заключается в том, что дополнение не обрабатывает произвольное количество аргументов.
Вместо этого вам нужно будет написать augment_from_list(vectors)
который принимает один аргумент (список векторов) и дополняет их.
И это только для дополнения - вам понадобятся аналогичные помощники, чтобы расширить встроенные функции для обработки произвольного числа аргументов.