【问题标题】:Piecewise functions in MATLABMATLAB 中的分段函数
【发布时间】:2018-04-25 07:45:26
【问题描述】:

我今年才开始使用 MATLAB for Uni,作为一个家庭作业测验问题,我被要求创建一个分段函数(我称之为“piecewise_method”),它能够在“x”上建立一个不同的方程" 取决于 "x" 是低于 0、介于 0 和 8 之间还是高于 8。这是我目前编写的代码。

function solution = piecewise_method(x)

% given the value of the input x, the function
% piecewise_method will choose from one of the three specified
% equations to enact upon the given value of x
% and give the user a solution

solution = zeros(size(x));
e = exp(1);

for j = 1:size(x)
    a = x(j);

    if a < 0
        solution(j) = -a.^3 - 2*a.^2 + 3*a;
    elseif (a >= 0) && (a <= 8)
        solution(j) = (12/pi)*sin(pi*a./4);
    else
        solution(j) = ((600.*e.^(a-8))./(7*(14+6.*e.^(a-8))) - 30/7);
    end
end

使用输入运行时...

x = -3:12

它为变量解产生这个结果...

解决方案 =

 0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0

现在这向我表明该数组正在正确创建,但由于某种原因,for 循环没有正常运行,或者没有按预期运行。我尝试从基本级别开始多次重建 for 循环,但是当我开始输入方程式时,它又开始分崩离析,所以我相信我的方程式可能有问题(这就是为什么我到处都放括号的原因,以防万一)。

问题还要求我使用if语句,所以我无法尝试使用其他方法来产生分段方法函数,并且从我的搜索来看,似乎没有很多分段函数中if语句的例子.

如果您能提供任何可以帮助我使用此功能的建议,将不胜感激,谢谢!

附:如果您有任何建议可以在将来改进我的问题,那也很好!

【问题讨论】:

  • 您只需将for j = 1:size(x) 替换为for j = 1:numel(x)size(x) 将为 x 的行和列返回 [1 16],而 numel(x) 将返回元素的数量,而与 x 是行向量还是列向量无关。更一般地说,断点是你的朋友:在你的函数中放置一个断点,然后一步一步地遍历它,查看变量值!
  • 哦,对了,在你提到它之前,我没有看到关于断点的选项。 MATLAB 给我一个错误关于索引函数,当我尝试你的方法时,可能还有其他需要先完成的事情吗?
  • 错误是什么?无论如何,我的方法与下面答案中提出的方法完全相同,所以如果该方法有效,我的方法也应该...
  • 我明白了,我想我一直很困惑。但它现在可以工作了,谢谢。
  • 不要使用e.^(a-8),使用exp(a-8) 会更精确(而且可能更快)。注意是相同的字符数!

标签: matlab piecewise


【解决方案1】:

您应该在for 循环中使用length 而不是size

size 函数的输出是 x 的维度,对于您的 x=-3:12 示例,它返回 size(x)=[1 16]。然后您的for 循环将为j=1:size(x) 运行,即j=1:1,即j=1

length 的输出是x 的最大数组维度的长度,如here 所列。在您的示例中:length(x) = 16,然后是 j=1:length(x)=1:16

或者,您可以使用size(x,2),它将返回x 的第二维的大小,在这种情况下与length 相同。

【讨论】:

  • 感谢您的反馈。另外,如果您不介意我问,有没有办法改进我的问题以备将来使用?
  • 我认为你的问题很清楚而且写得很好。查看对您的问题所做的编辑,了解如何正确地将代码添加到其中,以便于阅读。当然,正如 cmets 中提到的,尝试使用断点进行调试并自己查找问题 - 这是最好的学习方式。如果我的回答对您有帮助,请按“V”接受它 - 这支持我并让其他人知道您收到了一个令您满意的答案。
【解决方案2】:

如 cmets 和 RadioJava's answer 中所述,您需要检查循环。我会使用size(x,2)x 中的列数)或numel(x)x 中的元素数)。

for j = 1:numel(x)
    % ...

其他人推荐length(x),即max(size(x))。我通常会尽量避免这种情况,因为它不明确您要查找矩阵的哪个维度。

除了只是重复信息之外,我想展示您可以通过逻辑索引更有效地做到这一点,并完全消除有问题的循环......

function solution = piecewise_method(x)

% given the value of the input x, the function
% piecewise_method will choose from one of the three specified
% equations to enact upon the given value of x
% and give the user a solution

solution = zeros(size(x));
e = exp(1);

idx = (x<0);
solution(idx) = -x(idx).^3 - 2*x(idx).^2 + 3*x(idx);
idx = (x>=0 & x<=8);
solution(idx) = (12/pi)*sin(pi*x(idx)/4);
idx = (x>8);
solution(idx) = (600*e.^(x(idx)-8))./(7*(14+6*e.^(x(idx)-8))) - 30/7;

请注意,您可以轻松地在数组中包含条件和(匿名)函数并循环它们以使其更加灵活。

【讨论】:

  • 感谢您的建议和回答。作为我回应的一部分,虽然我确实需要实现一系列 if 和 elseif 语句,否则我会尝试像你上面提出的那样。也让我可以阅读更多关于这种类型的函数(你能够使用“x(idx)”等的方式)你会怎么称呼它?比如我应该搜索什么以了解更多关于在未来的程序中使用这种方法的信息?感谢您的帮助。
  • 如答案所述,它被称为logical indexing
  • @Wolfie 我想建议这个解决方案,因为我认为它会更快......但是在实现它之后,它花费了循环功能的两倍!出于好奇,你有没有偶然测试过它?
  • 循环不一定很慢。不,我没有测试它,您是否只使用 OP 给出的非常小的示例进行测试?在千分之一秒的运行时,我无法想象任何相关的基准测试都是可靠的......
  • 不,我尝试了 500 个元素的数组......但你是对的,也许更大的数组会改变。没关系!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-01
  • 2015-08-23
  • 1970-01-01
相关资源
最近更新 更多