为什么这两种在 Octave 中绘制函数的方法不一致?

Why is there an inconstancy between these two ways of plotting a function in Octave?

上下文

我有一个名为 ibm 的函数,我用一个简单的 if 条件定义了它:在某个值 (500) 之前它应该为 0,然后在该值之后是线性的:

function f = ibm(x)
  if(nargin != 1)
    usage("ibm(x)");
  endif
  if(x <= 500)
    f = 0;
  else
    f = (x-500) *0.02;
  endif
endfunction

然后在一个脚本中,我想用 x 在 0 到 1000 的范围内绘制这个函数,所以我尝试用一​​个简单的

来绘制它
x=0:1:1000;
plot(x,ibm(x));

但是结果并没有显示出我想要的:它显示了一个线性函数,没有平坦部分(见图1,红色图表)。它与函数结果不对应,我检查了一些低于 500 的值:如果我键入 ibm(34) 结果如预期的那样为 0,但不在图中。
为什么会出现这种差异?

所以在对这个问题疑惑了一段时间后,我尝试在for循环中“手动”添加结果值,然后结果变成了我预期的结果(见图2,蓝色图表)。

这里有完整的代码示例 (MVE):

这会产生具有相同函数 ibm 的两个数字(错误的和正确的)。

1; # start of file should not start with function, so useless statement here
# The function we want to plot
function f = ibm(x)
  if(nargin != 1)
    usage("ibm(x)");
  endif
  if(x <= 500)
    f = 0;
  else
    f = (x-500) *0.02;
  endif
endfunction

# For figure 1, directly computed (wrong plot result, in red)
x=0:1:1000;
figure(1);
plot( x, ibm(x), "xr");
xlabel("x");
ylabel("ibm(x)");
title("ibm(x) directly computed");
legend("ibm(x)");

# for figure 2, in for loop (correct plot result, in blue)
a = [];
for(i=x)
  a = [a, ibm(i)];
end
figure(2);
plot(x,a, "ob");
xlabel("x");
ylabel("ibm(x)");
title("ibm(x) in for loop");
legend("ibm(x)");

问题

为什么第一种(也是最直接的)方法不能产生我想要的图形结果?我应该总是用 for 循环绘制图形吗?就好像 plot 函数没有考虑 if(x <= 500) 而直接进入线性部分。

请注意,我什至尝试了使用 Scilab 绘图的第一种方法,结果相同(红色错误曲线),但我仍然不知道为什么。

数字

错误

问题是您对 ibm 的定义。您只为长度为 1 的 x 编码。代码对 ibm([0,1000]) 有何作用? if 条件如何对 x 做出反应?

我认为这是对矢量化如何发生的混淆。 Octave 不会调用 1000 ibm 每个都有自己的 x,但会调用 ibm 一次,所有 1000 x 作为输入。你如何处理矢量输入取决于你,而你的函数根本没有。

例如,如果您将 if 替换为:

 f = (x-500) *0.02;
 f(x<500) = 0 ;

该函数应该有效(因此该图应该有效),因为这两条线都是矢量化的并且适用于任何大小的 x


如果您需要更多信息,请查看 octaves manual for if

The condition in an if statement is considered true if its value is nonzero, and false if its value is zero. If the value of the conditional expression in an if statement is a vector or a matrix, it is considered true only if it is non-empty and all of the elements are nonzero. The conceptually equivalent code when condition is a matrix is shown below.

if (matrix) ≡ if (all (matrix(:)))