TI-NSpire 为矢量叉积动态创建变量
TI-NSpire dynamically create variables for vector cross product
好的,我正在尝试在 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
在 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 中的 "programming language" 非常有限。第一个问题是 augment 不能处理任意数量的参数。
相反,您需要编写一个 augment_from_list(vectors)
,它接受一个参数(向量列表)并扩充它们。
这只是为了扩充——您将需要类似的助手来扩展内置函数以处理任意数量的参数。
OP在这里。我觉得我想出的解决方案适合适当的响应,而不是简单的更新。
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>。不过,如果有人能证实这一点,我将不胜感激。
这整个函数之所以有效,是因为计算器处理多项式的方式。所以我的 'unit' 函数中的向量是 1、unit、unit^2、unit^3 等。因此,一旦它确定行列式,'unit' 变量的系数就是向量的分量。此外,在测试过程中,我发现如果行列式导致零乘以多项式的主幂(比如单位 ^ 3),那么向量将是一个短分量(但如果 0 乘以任何功率较低的项,但不是主要功率项,则没有问题)。如果行列式结果为 0,则结果只是一个空列表。带有嵌套 for 循环的 if 循环通过确保每个组件都在适当长度的列表中来解决这个问题(从而防止混淆并导致执行者必须做额外的工作才能恢复到适当的列表长度) 并且这些组件位于正确的位置。
我确信代码可以改进并变得更快,但我对结果很满意。感谢大家的帮助。
好的,我正在尝试在 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
在 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 中的 "programming language" 非常有限。第一个问题是 augment 不能处理任意数量的参数。
相反,您需要编写一个 augment_from_list(vectors)
,它接受一个参数(向量列表)并扩充它们。
这只是为了扩充——您将需要类似的助手来扩展内置函数以处理任意数量的参数。
OP在这里。我觉得我想出的解决方案适合适当的响应,而不是简单的更新。
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>。不过,如果有人能证实这一点,我将不胜感激。
这整个函数之所以有效,是因为计算器处理多项式的方式。所以我的 'unit' 函数中的向量是 1、unit、unit^2、unit^3 等。因此,一旦它确定行列式,'unit' 变量的系数就是向量的分量。此外,在测试过程中,我发现如果行列式导致零乘以多项式的主幂(比如单位 ^ 3),那么向量将是一个短分量(但如果 0 乘以任何功率较低的项,但不是主要功率项,则没有问题)。如果行列式结果为 0,则结果只是一个空列表。带有嵌套 for 循环的 if 循环通过确保每个组件都在适当长度的列表中来解决这个问题(从而防止混淆并导致执行者必须做额外的工作才能恢复到适当的列表长度) 并且这些组件位于正确的位置。
我确信代码可以改进并变得更快,但我对结果很满意。感谢大家的帮助。