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

标签 matlab printf

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

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

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

  1. 数据strrep() 输出使用sprintf()。这是以逐行方式完成的,以节省内存。此解决方案比简单的 fprintf() 花费的时间几乎多 10 倍。优点是内存开销小。
  2. 与选项1. 相同,但翻译是一次性完成整个数据。此解决方案速度更快,但容易出现内存不足异常。这种方法的问题是我不想不必要地复制数据

代码:

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  

输出:

Elapsed time is 1.651089 seconds. % Regular fprintf()
Elapsed time is 11.529552 seconds. % Option 1
Elapsed time is 2.305582 seconds. % Option 2

现在问题...

与简单的 fprintf() 相比,我对使用我的解决方案的内存开销和时间损失不满意。
我的理由是 'NaN''Inf''-Inf' 字符串是保存在 *printf()*2str() 实现。有什么办法可以在运行时改变它们的值吗?
例如,在 C# 中,我会更改 System.Globalization.CultureInfo.NumberFormat.NaNSymbol 等,如 here 所述。 .

最佳答案

在评论中提到的有限情况下,许多(未知,根据数据集变化)列可能完全是 NaN(或 Inf 等),但是否则没有不需要的 NaN 值,另一种可能性是检查第一行数据,组装一个直接写入 \\m 字符串的格式字符串,然后使用它 while告诉 fprintf 忽略包含 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])');

关于matlab - 在 Matlab 中更改 fprintf() 的默认 NaN 表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25061400/

相关文章:

c - 为什么我的打印当前日期时间(C语言)给出了不同的答案

matlab - 查找满足多个条件中的任何一个的元素

performance - 比较BSXFUN和REPMAT

matlab - 有没有办法在嵌套函数中声明局部变量?

c - 尝试在 C 中打印 10 行,每行 100 个数组值

matlab - 当 printf 位于从 s-function 调用的单独的 c 文件中时,如何使它工作?

matlab - 从不同目录运行 Matlab GUI

arrays - 如何获取数组的镜像(MATLAB)?

c - 在 printf 函数内扩展动态宏

C++11 可变参数 Printf 性能