在Matlab中更改fprintf()的默认NaN表示

时间:2014-07-31 14:24:14

标签: matlab printf

我正在尝试以其他应用程序可以理解的格式从Matlab导出数据...为此,我需要更改NaNInf-Inf字符串(即默认情况下,Matlab会将这些值打印到//m//inf+//Inf-

总的来说,我知道如何做到这一点。我在询问如何(以及是否可能)在Matlab中利用一个特定的东西。实际问题位于最后一段。

我尝试过两种方法(代码如下)。

  1. 数据sprintf()输出上使用strrep()。这是以逐行方式完成的,以节省内存。此解决方案比简单fprintf()花费的时间多近10倍。它的优点是内存开销很低。
  2. 与选项 1。相同,但转换是在整个数据上完成的。此解决方案更快,但容易出现内存不足异常。我对这种方法的问题是我不想不必要地复制数据
  3. 代码:

    rows = 50000  
    cols = 40  
    data = rand(rows, cols); % generate random matrix  
    data([1 3 8]) = NaN; % insert some NaN values  
    data([5 6 14]) = Inf; % insert some Inf values  
    data([4 2 12]) = -Inf; % insert some -Inf values  
    
    fid = fopen('data.txt', 'w'); %output file  
    
    %% 0) Write data using default fprintf  
    format = repmat('%g ', 1, cols);  
    
    tic  
    fprintf(fid, [format '\n'], data');  
    toc  
    
    %% 1) Using strrep, writing line by line  
    fprintf(fid, '\n');  
    tic  
    for i = 1:rows  
        fprintf(fid, '%s\n', strrep(strrep(strrep(sprintf(format, data(i, :)), 'NaN', '//m'), '-Inf', '//inf-'), 'Inf', '//inf+'));  
    end  
    toc  
    
    %% 2) Using strrep, writing all at once  
    fprintf(fid, '\n');  
    format = [format '\n'];  
    tic  
        fprintf(fid, '%s\n', strrep(strrep(strrep(sprintf(format, data'), 'NaN', '//m'), '-Inf', '//inf-'), 'Inf', '//inf+'));  
    toc  
    

    输出:

      

    经过的时间是1.651089秒。 %Regular fprintf()
      经过的时间是11.529552秒。 %选项1
      经过的时间是2.305582秒。 %Option 2

    现在问题......

    与简单fprintf()相比,我对使用我的解决方案所耗费的内存开销和时间不满意 我的理由是,'NaN''Inf''-Inf'字符串是保存在*printf()*2str()实现中的某个变量中的简单数据。有没有办法在运行时更改它们的值?
    例如,在C#中,我会将System.Globalization.CultureInfo.NumberFormat.NaNSymbol等更改为explaind here

1 个答案:

答案 0 :(得分:1)

在评论中提到的有限情况下,许多(未知,每个数据集更改)列可能完全NaN(或Inf等),但没有不需要的{{否则,另一种可能性是检查第一行数据,汇编直接写入NaN字符串的格式字符串,并在告诉\\m忽略包含{fprintf的列时使用它。 1}}或其他不需要的值。

NaN

通过我的两列y = ~isnan(data(1,:)); % find all non-NaN format = sprintf('%d ',y); % print a 1/0 string format = strrep(format,'1','%g'); format = strrep(format,'0','//m'); fid = fopen('data.txt', 'w'); fprintf(fid, [format '\n'], data(:,y)'); %pass only the non-NaN data fclose(fid); 检查,NaN与您的"常规"几乎相同fprintf并且比循环更快 - 不考虑生成fprintf的初始化步骤。如果你还需要考虑+/- format,那么将它设置为自动生成格式字符串会更加频繁,但肯定是可能的。可能还有一种更简洁的方式来生成Inf

工作原理:

您可以传入数据的子集,也可以将任何您喜欢的文本插入到格式字符串中,这样如果每一行都有相同的所需文本"在同一地点(在这种情况下为format列和我们想要替换" NaN"),我们可以将我们想要的文本放在该位置,然后只是不将数据的这些部分传递给NaN首先是fprintf。尝试命令行的一个更简单的例子:

x = magic(5);
x(:,3)=NaN
sprintf('%d %d ihatethrees %d %d \n',x(:,[1,2,4,5])');