在 Matlab 中将 A^2 表示为 A * A

Express A^2 as A * A in Matlab

因此,我在 Matlab 中有一个非常长的符号表达式,我想将其 copy/paste 转换为 JavaScript 代码,以便为它制作数值解的动画。问题是我的代码中的某些地方我得到指数(主要是 ^2),而我宁愿让 Matlab 将它表示为 A*A。

我有多个(和不同的)表达式,例如

cos(th2t)^2 

我宁愿表达为

cos(th2t)*cos(th2t)

我有什么办法可以做到这一点?另一种方法是之后使用文本编辑器搜索 2 的幂并替换它,但是有多个不同的表达式,因此需要一些时间...

这是我最终得到的表达式之一的示例:

(J31*(2*ddth2t*cos(th1t) - 2*w12*w13 - 4*dth1t*dth2t*sin(th1t) - 4*dth2t*w13*sin(th1t) + dth1t^2*sin(2*th2t)*cos(th1t) - w12^2*sin(2*th2t)*cos(th1t) + w13^2*sin(2*th2t)*cos(th1t) + 2*dth2t*w11*sin(2*th2t) + 2*w12*w13*cos(th2t)^2 + ddth1t*sin(2*th2t)*sin(th1t) + 4*dth1t*dth2t*cos(th2t)^2*sin(th1t) + 2*dth1t*w13*sin(2*th2t)*cos(th1t) + 4*dth2t*w13*cos(th2t)^2*sin(th1t) + w11*w12*sin(2*th2t)*sin(th1t) + 4*dth1t*w12*cos(th1t)^2*cos(th2t)^2 - 2*dth1t*w11*sin(2*th1t)*cos(th2t)^2 - 2*dth2t*w11*sin(2*th2t)*cos(th1t)^2 + 2*w12*w13*cos(th1t)^2*cos(th2t)^2 - w11*w13*sin(2*th1t)*cos(th2t)^2 - 4*dth2t*w12*cos(th1t)*cos(th2t)*sin(th1t)*sin(th2t)))/(2*(J11 + J31))

This answer 建议您可以在 Javascript 中调用指数运算符,例如A**2。因此,您可以将 ^ 的所有实例替换为 **。 (来自评论的解决方案)

如果您想依赖 ** 运算符,Steve 的回答应该可以正常工作。但是,由于该运算符不受官方支持,并且该解决方案不能直接回答 OP 的问题,因此这里有一个函数可以扩展符号表达式中的指数。

function [ text ] = remove_powers( exp )
%Cleans the powers from T, and return expanded text representation

    % Define functions
    enclose =@(t) ['(' t ')'];
    expand_pow=@(b,p) strjoin(strcat(cell(1,p),enclose(char(b))),'*');
    count_pow=@(s) arrayfun(@(k) count(char(s(k)),'^'), 1:length(s));
    sym2str = @(s) strrep(char(s), ' ', '');

    % Check for fractions
    [N,D]=numden(exp);
    if ~isequal(D,sym(1))
        % pass up the num and den
        text = [remove_powers(N) '/' enclose(remove_powers(D))];
    else
        % Split a into subterms
        Ts = children(exp);

        % Clean children
        has_pow=count_pow(Ts)>0;
        text = sym2str(exp);
        if sum(count_pow(Ts))<count_pow(exp)
            % We have removed a power, clean it, expand it, and pass up
            text = expand_pow(remove_powers(Ts(1)),Ts(2));
        else
            % Just clean the unclean children and pass up
            for t=Ts(has_pow)
                text = strrep(text,sym2str(t),remove_powers(t));
            end
        end
    end
end

该函数使用 Matlab 中的 children 函数递归清理每个子表达式并在父级中替换它(作为文本)。这种方法比使用正则表达式更好,因为它避免了解析语法的问题,正如史蒂夫在评论中提到的 cos(x^2+2*y)^2.

这是一个很好的例子:

syms x y real
exp = cos(x^2+2*y)^2;
cleaned_exp = remove_powers(exp)

输出:(cos(2*y+(x)*(x)))*(cos(2*y+(x)*(x)))

请注意,由于 Matlab 正在执行解析,因此无需解析“^”运算符的优先顺序,这可能很难用正则表达式完成。

测试 OP 示例:

syms ddth1t dth1t th1t ddth2t dth2t th2t w11 w12 w13 J11 J31 real
exp = (J31*(2*ddth2t*cos(th1t) - 2*w12*w13 - 4*dth1t*dth2t*sin(th1t) - 4*dth2t*w13*sin(th1t) + dth1t^2*sin(2*th2t)*cos(th1t) - w12^2*sin(2*th2t)*cos(th1t) + w13^2*sin(2*th2t)*cos(th1t) + 2*dth2t*w11*sin(2*th2t) + 2*w12*w13*cos(th2t)^2 + ddth1t*sin(2*th2t)*sin(th1t) + 4*dth1t*dth2t*cos(th2t)^2*sin(th1t) + 2*dth1t*w13*sin(2*th2t)*cos(th1t) + 4*dth2t*w13*cos(th2t)^2*sin(th1t) + w11*w12*sin(2*th2t)*sin(th1t) + 4*dth1t*w12*cos(th1t)^2*cos(th2t)^2 - 2*dth1t*w11*sin(2*th1t)*cos(th2t)^2 - 2*dth2t*w11*sin(2*th2t)*cos(th1t)^2 + 2*w12*w13*cos(th1t)^2*cos(th2t)^2 - w11*w13*sin(2*th1t)*cos(th2t)^2 - 4*dth2t*w12*cos(th1t)*cos(th2t)*sin(th1t)*sin(th2t)))/(2*(J11 + J31));

cleaned_exp = remove_powers(exp);
isequal(sym(cleaned_exp),exp)   % This should be 1
count(cleaned_exp,'^')          % This should be 0

正如预期的那样,新表达式与原始表达式等效,但没有“^”符号。