wanglu 发表于 2010-10-7 07:40:42

关于数组存储方式

数组存储方式有按行顺序存储和按列顺序存储两种,Fortran、matlab是按列优先的,而C/C++、Pascal等是按行优先的,哪一种更好呢?

pengyehui9527 发表于 2010-10-7 08:18:48

这个无所谓更好吧,知道这么存储了,就知道怎么去找了

wanglu 发表于 2010-10-7 09:03:45

这个无所谓更好吧,知道这么存储了,就知道怎么去找了
pengyehui9527 发表于 2010-10-7 08:18 http://forum.simwe.com/images/common/back.gif
也就是说如何使用只是个习惯问题,对运行效率没有影响?
谢谢!

lengyunfeng 发表于 2010-10-7 09:37:29

除了运算顺序有所变换以外,个人觉得是一样的。比如A*X的运算,如果是按列的话,它算的时候就会把X的某一列乘A的各列后按列相加,如果是按行的话,它可能就是将A的某一行乘X的各行后按行相加。我记得矩阵运算里各类定理均是按行运算方法对应的有一个按列运算方法,甚至连行列式都一样。这只是个运算顺序的区别,就像写字一样,古代人竖着写,我们横着写罢了。当然这还有个习惯问题,我们现在所写的方程式一般是A*X=b,其中X一般是一个列向量,这样如果按列计算就很简单,按行的话就要多几次循环了。

wanglu 发表于 2010-10-7 09:46:45

本帖最后由 wanglu 于 2010-10-7 09:48 编辑

4# lengyunfeng
恩,我也感觉在细微之处还是有点区别。
例如一个矩阵,如果按列存储,则计算列向量的和就比较方便;如果按行存储,计算行向量的和则比较方便。

matlab中sum(A,1)和sum(A,2)的效率似乎不一样吧?

wanglu 发表于 2010-10-7 09:58:04

Forcal代码:!using["math","sys"];
mvar:
oo{p=rand},
t0=clock(),
oo{Sum},
printff{"\r\n按列求和时间: {1,r}",/1000},
t0=clock(),
oo{Sum},
printff{"\r\n按行求和时间: {1,r}",/1000}结果:
按列求和时间: 0.375
按行求和时间: 4.7e-002

qibbxxt 发表于 2010-10-7 12:12:10

我觉得哪个更好应该很难说,对于我们而言,只要知道了它的存储方式,在写程序的时候就按照它的规则来写就可以了,matlab做循环的时候,列优先,效率会高一些,可以看roc的书中有对比的

wanglu 发表于 2010-10-7 15:21:07

我觉得哪个更好应该很难说,对于我们而言,只要知道了它的存储方式,在写程序的时候就按照它的规则来写就可以了,matlab做循环的时候,列优先,效率会高一些,可以看roc的书中有对比的
qibbxxt 发表于 2010-10-7 12:12 http://forum.simwe.com/images/common/back.gif
看来确实这样,行优先或者列优先无关紧要,是一个习惯及使用时需要注意的问题。

在设计一个基于矩阵的数学库FcMath时,这个是首先要考虑的问题,看来是多虑了,呵呵,谢谢大家讨论。

我想知道的另一个问题是:matlab的矢量化到底是什么东东?

wanglu 发表于 2010-10-7 15:33:14

但我又想到了行优先的一个优点,Forcal代码: !using["math"];
oo{array.rand[].outm};该程序的作用是生成多维数组,用随机数初始化,然后列表输出。

结果:
(0,0,0,*)         0.273       0.983      0.94       0.757       0.995
(0,0,1,*)          0.97       0.749       0.176       0.965       0.192
(0,1,0,*)         0.735       0.478       0.353       0.509       0.194
(0,1,1,*)         0.149       0.582   2.99e-002       0.674       0.923
(0,2,0,*)         0.324       0.114       0.971       0.783       0.501
(0,2,1,*)         0.372       0.132       0.964       0.284       0.661
(1,0,0,*)         0.454       0.952   9.49e-002   9.22e-002       0.485
(1,0,1,*)         0.479       0.606   2.43e-002   2.01e-002       0.531
(1,1,0,*)          0.74   6.67e-002       0.107       0.341       0.667
(1,1,1,*)   7.88e-002    4.3e-002       0.395       0.811      0.17
(1,2,0,*)         0.374       0.426       0.841         0.7       0.898
(1,2,1,*)         0.419       0.682       0.277       0.661       0.609

星号表示一行数据。可以看出,列表和行优先的内存存储是一致的,在内存中就是一行一行地连续存储的。

如果是列优先是不是有点麻烦?

lengyunfeng 发表于 2010-10-7 16:36:48

9# wanglu
不同的语言默认可能不一样吧,你用的forcal语言矩阵索引最后一位数代表行,matlab里却是代表列,所以行好一些还是列好一些只能针对某一种语言来讲。正如我前面所说的,列操作更符合我们实际当中遇到的情况,所以可能更常用一些,你可以看一下Gilbert Strang的linear algebra,里面很详细的介绍了矩阵的行、列操作所来的背景,也说了为什么列操作更为我们所用。至于矢量化编程是什么,我是这样理解的,很多语言对矩阵进行运算的时候,往往需要采用循环方式调用矩阵内部的某一个具体元素进行,而matlab里的矢量化编程则是将矩阵看作列(矢量)的组合,以列(矢量)为单位进行编程。举个简单的例子,我们有一个向量共有n个元素,要算它里面各个元素对应的sin函数值或者其它函数值,对于一般性的语言来说,可能需要作一个循环,把向量中的每个元素调出来并进行函数求值操作,而对于matlab语言来说,要做的只是将整个向量一起传递给这个函数,即可获得结果,无需循环。

wanglu 发表于 2010-10-7 18:17:14

10# lengyunfeng
这么说,对数值计算来说,还是列优先要好些?

Gilbert Strang的linear algebra是英文版,我看起来比较费劲,不过还是要感谢你提供了这个信息。

关于matlab里的矢量化运算,Fortran里面也有,只不过不叫矢量化,而且不如matlab的函数全面,其原因应该是Fortran是高效的编程语言,实现matlab的函数功能不是很麻烦,而且高效,故不需要提供那么多函数。当然,matlab的矩阵函数是特别优化的,一般人用Fortran编程,达不到这样的效率。

所谓的“矢量化”函数,Forcal里面目前也有一部分,例如:
!using["math"];
oo{rand.outm[].Sin[].outm[]};
说明:生成3×4随机数矩阵并输出,对矩阵每个元素求正弦并输出。

结果:

       0.606339   2.42615e-002   2.01263e-002       0.530701
       0.739822   6.66809e-002       0.107224       0.341187
       0.667252   7.88269e-002   4.29535e-002       0.394836

       0.569862   2.42591e-002    2.0125e-002       0.506138
       0.674157   6.66315e-002       0.107018       0.334605
       0.618829   7.87453e-002   4.29403e-002       0.384657

页: [1]
查看完整版本: 关于数组存储方式