Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 三角矩阵系数的指数算法_Algorithm - Fatal编程技术网

Algorithm 三角矩阵系数的指数算法

Algorithm 三角矩阵系数的指数算法,algorithm,Algorithm,我想这一定很简单,但我做不好 我有一个MxM三角矩阵,它的系数一行一行地存储在向量中。 例如: M = [ m00 m01 m02 m03 ] [ m11 m12 m13 ] [ m22 m23 ] [ m33 ] 存储为 coef[ m00 m01 m02 m03 m11 m12 m13 m22 m23 m33 ] 现在,我正在寻找一种非递归算法,它给出矩阵大小m和系数数组索引I unsigned i

我想这一定很简单,但我做不好

我有一个MxM三角矩阵,它的系数一行一行地存储在向量中。 例如:

M =   [ m00 m01 m02 m03 ] 
      [     m11 m12 m13 ]
      [         m22 m23 ]
      [             m33 ]
存储为

coef[ m00 m01 m02 m03 m11 m12 m13 m22 m23 m33 ]
现在,我正在寻找一种非递归算法,它给出矩阵大小
m
和系数数组索引
I

unsigned int row_index(i,M)

它所指的矩阵元素的。所以
行索引(9,4)==3
列索引(7,4)==2
等。如果索引计数是基于零的


编辑:已经给出了几个使用迭代的回复。有人知道代数表达式吗?

我花了一些时间才明白您需要什么!:)

无符号整数行索引(整数i,整数m)
{
int iCurrentRow=0;
int-iTotalItems=0;
对于(int j=m;j>0;j--)
{
iTotalItems+=j;
如果((i+1)0;j--)
{
iTotalItems+=j;
如果((i+1)它必须是

i == col + row*(M-1)-row*(row-1)/2
所以找到col和row的一种方法是迭代row的可能值:

for(row = 0; row < M; row++){
  col = i - row*(M-1)-row*(row-1)/2
  if (row <= col < M) return (row,column);
}
for(行=0;行如果(行可能有一个聪明的一行,但是(减去任何错误检查):

unsigned int行索引(unsigned int i,unsigned int M){
无符号整数行=0;
无符号整数增量=M-1;
对于(无符号整数x=delta;x
这里有一个代数(主要)解决方案:

unsigned int row_index( unsigned int i, unsigned int M ){
    double m = M;
    double row = (-2*m - 1 + sqrt( (4*m*(m+1) - 8*(double)i - 7) )) / -2;
    if( row == (double)(int) row ) row -= 1;
    return (unsigned int) row;
}


unsigned int column_index( unsigned int i, unsigned int M ){
    unsigned int row = row_index( i, M);
    return  i - M * row + row*(row+1) / 2;
}

编辑:固定了行索引()

在这个回复的最后一行,解释如下:-)

系数数组的第一行(索引中的第0行)有M个元素,第二行(第1行)有M-1个元素,依此类推,总共有M+(M-1)+…+1=M(M+1)/2个元素

从末尾开始工作稍微容易一些,因为系数数组的最后一行(第M-1行)总是有1个元素,第二行(第M-2行)有2个元素,第M-3行有3个元素,依此类推。最后K行占据系数数组的最后K(K+1)/2个位置

现在假设在系数数组中有一个索引i,在大于i的位置有M(M+1)/2-1-i个元素,称这个数字为i’;你想找到最大的k,使得k(k+1)/2≤ i'。这个问题的形式正是你痛苦的根源——据我所见,你无法避免平方根:-)

好吧,我们还是这样做吧:k(k+1)≤ 2i’指(k+1/2)2-1/4≤ 2i',或相当于k≤ (sqrt(8i'+1)-1)/2.让我把最大的k称为k,那么有k行是后面的(总共M行中),所以行索引(i,M)是M-1-k。至于列索引,i'中的k(k+1)/2个元素在后面的行中,所以这一行中有j'=i'-k(k+1)/2个后面的元素(总共有k+1个元素),所以列索引是k-j'。[或者等效地,这一行从末尾的(K+1)(K+2)/2开始,所以我们只需要从i:i-[M(M+1)/2-(K+1)(K+2)/2中减去这一行的起始位置。令人振奋的是,这两个表达式给出了相同的答案!]

(伪)代码[使用ii而不是i',因为某些语言不允许使用名为i';-)的变量]:

当然,您可以通过将表达式替换为ii和K来将它们转换为一行程序。您可能需要小心精度错误,但有一些方法可以找到不需要浮点计算的整数平方根。此外,引用Knuth的话:“请注意上述代码中的错误;我只证明了它是正确的,没有尝试过。”

请允许我冒昧地说一句话:简单地将所有值保存在一个M×M数组中最多需要两倍的内存,并且根据您的问题,与算法改进相比,因子2可能微不足道,并且可能值得用可能昂贵的平方根计算换成您需要的更简单的表达式“我会的


[编辑:顺便说一句,您可以证明floor((sqrt(8ii+1)-1)/2)=(isqrt(8ii+1)-1)/2其中isqrt(x)=floor(sqrt(x))是整数平方根,除法是整数除法(截断;C/C++/Java等中的默认值)——因此,如果您担心精度问题,您只需要担心实现正确的整数平方根。]

我想了一下,得到了以下结果。请注意,一次可以同时获得行和列

假设:行从0开始。列从0开始。索引从0开始

符号

N=矩阵大小(原始问题中为M)

m=元素的索引

psuedo代码是

function ind2subTriu(m,N)
{
  d = 0;
  i = -1;
  while d < m
  {
    i = i + 1
    d = i*(N-1) - i*(i-1)/2
  }
  i0 = i-1;
  j0 = m - i0*(N-1) + i0*(i0-1)/2 + i0 + 1;
  return i0,j0
}
函数ind2subTriu(m,N)
{
d=0;
i=-1;
而d
和一些倍频程/matlab代码

function [i0 j0]= ind2subTriu(m,N)
 I = 0:N-2;
 d = I*(N-1)-I.*(I-1)/2;
 i0 = I(find (d < m,1,'last'));
 j0 = m - d(i0+1) + i0 + 1;
函数[i0 j0]=ind2subTriu(m,N)
I=0:N-2;
d=I*(N-1)-I*(I-1)/2;
i0=I(发现(d
你觉得怎么样


截至2011年12月,GNU/Octave中添加了实现这一点的非常好的代码。它们可能会扩展sub2ind和ind2sub。该代码目前可以作为私有函数找到,

ShreevatsaR的解释非常好,帮助我解决了我的问题。但是,为列索引提供的解释和代码给出了一点提示答案与问题要求的完全不同

重申一下,在i之后的行中有j'=i'-K(K+1)/2个元素。但是,与其他行一样,该行有M个元素。因此(从零开始的)列索引是y=M-1-j'

相应的伪代码为:

column_index(i, M):
  ii = M(M+1)/2-1-i
  K = floor((sqrt(8ii+1)-1)/2)
  jj = ii - K(K+1)/2
  return M-1-jj
ShreevatsaR给出的答案,K-j',是从矩阵的对角线开始计数(用零)时的列索引
unsigned int row_index( unsigned int i, unsigned int M ){
    double m = M;
    double row = (-2*m - 1 + sqrt( (4*m*(m+1) - 8*(double)i - 7) )) / -2;
    if( row == (double)(int) row ) row -= 1;
    return (unsigned int) row;
}


unsigned int column_index( unsigned int i, unsigned int M ){
    unsigned int row = row_index( i, M);
    return  i - M * row + row*(row+1) / 2;
}
row_index(i, M):
    ii = M(M+1)/2-1-i
    K = floor((sqrt(8ii+1)-1)/2)
    return M-1-K

column_index(i, M):
    ii = M(M+1)/2-1-i
    K = floor((sqrt(8ii+1)-1)/2)
    return i - M(M+1)/2 + (K+1)(K+2)/2
function ind2subTriu(m,N)
{
  d = 0;
  i = -1;
  while d < m
  {
    i = i + 1
    d = i*(N-1) - i*(i-1)/2
  }
  i0 = i-1;
  j0 = m - i0*(N-1) + i0*(i0-1)/2 + i0 + 1;
  return i0,j0
}
function [i0 j0]= ind2subTriu(m,N)
 I = 0:N-2;
 d = I*(N-1)-I.*(I-1)/2;
 i0 = I(find (d < m,1,'last'));
 j0 = m - d(i0+1) + i0 + 1;
column_index(i, M):
  ii = M(M+1)/2-1-i
  K = floor((sqrt(8ii+1)-1)/2)
  jj = ii - K(K+1)/2
  return M-1-jj