name ¶name n ¶("name") ¶("name", n) ¶运行与函数 name 关联的第 n 个示例代码块。
如果未指定 n,则运行所有示例。
示例代码块的首选位置是嵌入在脚本型 m 文件中,紧跟在它所演示的代码之后。或者,示例也可以存储在与该函数同名但没有扩展名的文件中,该文件位于 Octave 的加载路径上。为了将示例与常规脚本代码区分开,所有行都以 %! 作为前缀。每个示例还必须以关键字 "demo" 开头,且该关键字必须紧跟前缀(左侧对齐,中间无空格)。示例的其余部分可以包含任意 Octave 代码。例如:
%!demo
%! t = 0:0.01:2*pi;
%! x = sin (t);
%! plot (t, x);
%! title ("one cycle of a sine wave");
%! #-------------------------------------------------
%! # the figure window shows one cycle of a sine wave
请注意,代码会在执行前先显示出来,因此在末尾添加一个简单的注释就足够说明所展示的内容了。对于绘图,也可以使用 title 或 text 来添加标注。通常不需要在演示中使用 disp 或 printf。
演示在独立的函数环境中运行,无法访问外部变量。这意味着每个演示都必须有自己的初始化代码。或者,也可以将所有演示合并为一个大型演示,在各部分之间使用以下代码:
%! input ("Press <enter> to continue: ", "s");
但不鼓励这种用法。避免多个初始化块的其他技术包括:在每个绘图之间使用新的 figure 命令来创建多个图形,或者使用 subplot 将多个绘图放在同一个窗口中。
最后,由于 demo 在函数上下文中进行求值,因此无法在代码中定义新函数。在大多数情况下,匿名函数是一个很好的替代方案。如果必须使用函数块,那么可以使用代码 eval (example ("function", n)) 让 Octave 能够识别它们。但这种方法也有其自身的问题,因为 eval 一次只求值一行或一条语句。在这种情况下,函数声明必须用 "if 1 <demo stuff> endif" 包裹起来,其中 "if" 与 "demo" 位于同一行。例如:
%!demo if 1 %! function y = f(x) %! y = x; %! endfunction %! f(3) %! endif
name ¶name n ¶("name") ¶("name", n) ¶[codestr, codeidx] = example (…) ¶显示与函数 name 关联的第 n 个示例的代码,但不运行它。
如果未指定 n,则显示所有示例。
当使用输出参数调用时,示例将以字符串 codestr 的形式返回,codeidx 指示各个示例的结束位置。
完整说明请参阅 demo。
() ¶(directory) ¶对指定 directory 中所有 m 文件执行内置测试。
任何 C++ 源文件(*.cc)中的测试块也将被执行,以便用于动态链接的 oct 文件函数。
如果未指定目录,则对 Octave 函数搜索路径中的所有目录执行操作。
() ¶(directory) ¶对指定 directory 中所有 m 文件执行内置演示。
任何 C++ 源文件(*.cc)中的演示块也将被执行,以便用于动态链接的 oct 文件函数。
如果未指定目录,则对 Octave 函数搜索路径中的所有目录执行操作。
(f, init, max_n, f2, tol) ¶[order, n, T_f, T_f2] = speed (…) ¶确定表达式 (f) 在不同输入值 (n) 下的执行时间。
n 从 1 到 max_n 按对数间距取值。对于每个 n,都会计算初始化表达式 (init),以创建测试所需的任何数据。如果提供了第二个表达式 (f2),则比较两个表达式的执行时间。当没有输出参数调用时,结果将打印到标准输出并图形化显示。
f要计算的代码表达式。
max_n要运行的最大测试长度。默认值为 100。或者,可以使用 [min_n, max_n] 或使用 [n1, n2, …, nk] 精确指定 n 的值。
init函数参数值的初始化表达式。使用 k 表示测试编号,n 表示测试规模。此表达式应计算 f 使用的所有变量的值。注意,init 会先针对 k = 0 进行求值,因此整个测试系列中恒定不变的内容可以只计算一次。默认值为 x = randn (n, 1)。
f2要计算的另一个表达式,用于直接比较两个表达式的速度。默认值为 []。
tol用于比较表达式 f 和表达式 f2 的结果的容差。如果 tol 为正,则为绝对容差。如果 tol 为负,则为相对容差。默认值为 eps。如果 tol 为 Inf,则不进行比较。
order表达式的时间复杂度 O(a*n^p)。这是一个包含 a 和 p 字段的结构体。
n计算了表达式并且执行时间大于零的 n 值。
T_f为表达式 f 记录的非零执行时间(以秒为单位)。
T_f2为表达式 f2 记录的非零执行时间(以秒为单位)。如果需要,平均时间比可以通过 mean (T_f ./ T_f2) 简单地计算。
执行时间图的斜率反映了渐近运行时间 O(n^p) 的近似幂次。该幂次是在其被近似的区域(图的后半部分)绘制的。估计的幂次并不十分精确,但应足以确定算法的大致阶数。例如,它应该能够表明实现是否出乎意料地是 O(n^2) 而不是 O(n),原因是在每次循环中扩展向量而不是预先分配存储空间。在当前版本的 Octave 中,以下代码不是预期的 O(n)。
speed ("for i = 1:n, y{i} = x(i); endfor", "", [1000, 10000])
但如果预先分配了元胞数组 y,则结果符合预期的 O(n):
speed ("for i = 1:n, y{i} = x(i); endfor", ...
"x = rand (n, 1); y = cell (size (x));", [1000, 10000])
该函数会尝试估算单个操作的成本,但这非常不准确。可以通过让每个 n 执行更多工作来提高稳定性。例如:
speed ("airy(x)", "x = rand (n, 10)", [10000, 100000])
当比较两个不同的表达式(f、f2)时,如果新表达式更快,则加速比图上直线的斜率应大于 1。更好的算法斜率较小。通常,对算法进行向量化不会改变执行时间图的斜率,但会使其相对于原始图发生偏移。例如:
speed ("sum (x)", "", [10000, 100000], ...
"v = 0; for i = 1:length (x), v += x(i); endfor")
下面是一个更复杂的示例。假设有一个使用 for 循环的 xcorr 原始版本,以及一个使用 FFT 的第二个版本,那么可以如下比较不同滞后量的运行速度,或如下针对不同向量长度比较固定滞后量的运行速度:
speed ("xcorr (x, n)", "x = rand (128, 1);", 100,
"xcorr_orig (x, n)", -100*eps)
speed ("xcorr (x, 15)", "x = rand (20+n, 1);", 100,
"xcorr_orig (x, n)", -100*eps)
假设两个版本中的一个在 xcorr_orig 中,这将比较它们的速度和输出值。请注意,FFT 版本并非精确的,因此必须在比较中指定可接受的容差 100*eps。在这种情况下,应使用相对方式计算比较,即 abs ((x - y) ./ y),而不是绝对方式 abs (x - y)。
输入 example ("speed") 查看一些实际示例,或输入 demo ("speed") 来运行它们。
版权所有 © 2024-2026 Octave中文网
ICP备案/许可证号:黑ICP备2024030411号-4