Arrays 在Matlab上从二进制文件读取稀疏数组

Arrays 在Matlab上从二进制文件读取稀疏数组,arrays,matlab,Arrays,Matlab,我必须编写一个函数,从一个二进制文件(.dat)中读取一个二维双精度数组,该文件在一个列中结构化,其名称由函数的单输入参数提供。该文件的格式如下所示: 首先,有两个uint32编号,对应于数组的行数和列数。之后,有一个双倍数,即数组中非零元素的数量。然后,数组中的每个非零元素由文件中的两个uint32标量和一个双标量表示,顺序如下:行索引(uint32)、列索引(uint32)和值(double)。例如: 5 4 2 1 1 8 2 2 9 这意味着数组有5行4列,总共有2个非零元素。这些元素

我必须编写一个函数,从一个
二进制文件(.dat)
中读取一个二维双精度数组,该文件在一个列中结构化,其名称由函数的单输入参数提供。该文件的格式如下所示: 首先,有两个uint32编号,对应于数组的行数和列数。之后,有一个双倍数,即数组中非零元素的数量。然后,数组中的每个非零元素由文件中的两个uint32标量和一个双标量表示,顺序如下:行索引(uint32)、列索引(uint32)和值(double)。例如:

5
4
2
1
1
8
2
2
9
这意味着数组有5行4列,总共有2个非零元素。这些元素位于位置
(1,1)
(值为8)和位置
(2,2)
(值为9)。所有其他元素都等于0。因此,阵列将是:

8  0  0  0
0  9  0  0
0  0  0  0
0  0  0  0
0  0  0  0
函数必须返回从文件中读取的二维数组作为输出参数,如果打开文件时出现问题,函数将返回空数组。目前,我已尝试使用以下代码:

function A = sparse_array_in( filename )
fid = fopen( filename,'rt' );
if fid < 0
    A = [];
    return;
end
% Get total number of elements on the file
n = 0;
while (fgets(fid) ~= -1),
  n = n+1;
end
% Close then reopen
fclose(fid);
fid = fopen( filename,'rt' );
% Read size of array and number of non-zero elements
rows = fread( fid,1,'uint32' );
cols = fread( fid,1,'uint32' );
dims = [ rows,cols ];
non_zero = fread( fid,1,'uint32' );
% Create array of zeros
A = zeros( dims );   
% Fill array A with the values from the file
for i = 1:non_zero
    r = fread( fid,1,'uint32' );
    c = fread( fid,1,'uint32' );
    v = fread( fid,1,'double' );
    A(r,c) = v;
end
fclose( fid );
end
函数A=sparse\u array\u in(文件名)
fid=fopen(文件名,'rt');
如果fid<0
A=[];
返回;
结束
%获取文件上的元素总数
n=0;
而(fgets(fid)~=-1),
n=n+1;
结束
%关闭然后重新打开
fclose(fid);
fid=fopen(文件名,'rt');
%读取数组大小和非零元素数
行=fread(fid,1,'uint32');
cols=fread(fid,1,'uint32');
dims=[行,列];
非零=fread(fid,1,'uint32');
%创建零数组
A=零(dims);
%用文件中的值填充数组A
对于i=1:非零
r=fread(fid,1,'uint32');
c=fread(fid,1,'uint32');
v=fread(fid,1,'double');
A(r,c)=v;
结束
fclose(fid);
结束

但它似乎不起作用。我遗漏了什么?

您的代码存在一些问题:

  • 如果文件ID为负数,您不仅应该返回空数组(正如您所做的那样),还应该确保代码没有从该点开始。我会在分配给
    a
    的任务后立即粘贴一条
    return
    语句:

    if fid < 0
        A = [];
        return;
    end
    
    A =
    
         1     0     0     0     0     0     0
         0     2     0     0     0     0     0
         0     0     3     0     0     0     0
         0     0     0     4     0     0     0
         0     0     0     0     0     0     0
    
  • 您没有使用
    fread
    对。第二个参数告诉您要读入多少特定类型的数字。您正在使用1、2或3,这意味着您正在读取特定类型的1、2或3个数字。因为您使用
    fread
    读取每次呼叫的单个号码,所以它们都应该为1。此外,确定行的总数对我来说似乎是多余的。如果给定了非零元素的总数,为什么还要费心计算有多少行呢?您已经知道有多少个非零元素,所以只需从1迭代到尽可能多的非零数字。因此,请尝试以下方法:

    % Read size of array and number of non-zero elements
    rows = double(fread( fid,1,'uint32' )); %// Change
    cols = double(fread( fid,1,'uint32' )); %// Change
    dims = [ rows,cols ];
    non_zero = fread( fid,1,'uint32' ); %// Change
    % Create array of zeros
    A = zeros( dims );   
    % Fill array A with the values from the file
    for i = 1 : non_zero %// Change
        r = fread( fid,1,'uint32' ); %// Change
        c = fread( fid,1,'uint32' ); %// Change
        v = fread( fid,1,'double' ); %// Change
        A(r,c) = v;
    end
    %A = reshape( A,dims' ); %// Why are you reshaping?
    fclose( fid );
    
  • 次要评论:你为什么要重塑矩阵?如果你已经知道矩阵的行和列的位置,并且正把它们放在它们应该去的地方,为什么还要麻烦转置呢


    因此,根据上述注释,您的代码如下所示:

    function A = sparse_array_in( filename )
    fid = fopen( filename,'rt' );
    if fid < 0
        A = [];
        return; %// Change
    end
    
    % Read size of array and number of non-zero elements
    rows = fread( fid,1,'uint32'); %// Change
    cols = fread( fid,1,'uint32'); %// Change
    dims = [ rows,cols ];
    non_zero = fread( fid,1,'uint32' ); %// Change
    % Create array of zeros
    A = zeros( dims );   
    % Fill array A with the values from the file
    for i = 1:non_zero
        r = fread( fid,1,'uint32' ); %// Change
        c = fread( fid,1,'uint32' ); %// Change
        v = fread( fid,1,'double' ); %// Change
        A(r,c) = v;
    end
    %// Change - remove reshape
    fclose( fid );
    end
    
    这是一个5 x 7的矩阵,其中
    (1,1)=1,(2,2)=2,(3,3)=3,(4,4)=4
    ,具有4个非零值。我创建了一个二进制文件,然后使用上面修复的函数来获得结果:

    fid = fopen('sparse_binary.dat', 'w');
    fwrite(fid, 5, 'uint32');
    fwrite(fid, 7, 'uint32');
    fwrite(fid, 4, 'uint32');
    fwrite(fid, 1, 'uint32');
    fwrite(fid, 1, 'uint32');
    fwrite(fid, 1, 'double');
    fwrite(fid, 2, 'uint32');
    fwrite(fid, 2, 'uint32');
    fwrite(fid, 2, 'double');
    fwrite(fid, 3, 'uint32');
    fwrite(fid, 3, 'uint32');
    fwrite(fid, 3, 'double');
    fwrite(fid, 4, 'uint32');
    fwrite(fid, 4, 'uint32');
    fwrite(fid, 4, 'double');
    fclose(fid);
    A = sparse_array_in('sparse_binary.dat');
    
    对于
    A
    ,我得到:

    if fid < 0
        A = [];
        return;
    end
    
    A =
    
         1     0     0     0     0     0     0
         0     2     0     0     0     0     0
         0     0     3     0     0     0     0
         0     0     0     4     0     0     0
         0     0     0     0     0     0     0
    

    。。。这就是我们所期望的。

    我必须编写函数,然后在老师提供的评分器上提交,这个评分器会告诉你函数是否正确,但它不会说什么是错误的。我已经尝试了好几个小时,但没有效果,我希望有人能帮我找出我遗漏了什么,因为我看不到任何错误…你肯定需要创建自己的测试文件,因为你没有访问“分级器”文件的权限。从一个非常简单的开始,然后添加几个明显错误的额外代码,看看你的代码是否能够处理它们。我理解你所做的,但是评分员说它仍然不正确。我认为一个问题可能是分级器传递了文件,例如:
    5741123444
    ,甚至可能是在列向量上。这可能是导致您的解决方案出现错误的原因吗?@Hec46-我需要知道分级机传递数据的确切方式,否则我将永远无法得到正确的结果。我假设文本文件以空格分隔,回车分隔。@Hec46-您的文章中也没有明确说明数据的格式。请更新它,以便我们确切地知道文件的结构。对不起,让我们看看我是否可以更好地解释它。在第一个任务中,我被要求编写一个函数,给定一个数组和一个文件名,然后按照我在文章中解释的结构将这个数组写到一个二进制文件中。在测试之后,我看到它在一个列向量上运行。然后,这个
    .dat
    文件可以传递给第二个函数,它应该返回我传递给第一个函数的相同数组。老师刚刚告诉我,为了比较结果,我需要使用isequal()并得到一个1作为结果。我希望这能澄清一点,我现在就编辑这篇文章。谢谢大家!@Hec46-啊,如果它是二进制的,那么使用
    fread
    是合理的。我还是会等到你更新你的帖子。