4

我是面向对象编程的新手。经过一番压力,我终于设法在matlab的符号引擎muPad中定义了我自己的对象类。该引擎有自己的语言,其语法非常合乎逻辑,与matlab本身相似。

我想指出,没有必要知道 muPad 来帮助解决这个问题。我认为任何具有相关 OOP 经验的人都能够提供对该问题的更多见解。

我将从一些背景开始。我的班级叫Bx。它的对象有两个不同的属性,nk,使得n => k => 0。在 "Bx" 中正确定义的对象可能看起来像 Bx(0, 0),或 Bx(2, 2) 或 Bx(7 , 2)... "Bx" 中的每个对象都是唯一的;如果n1 = n2并且k1 = k2这意味着 Bx( n1 , k1 ) = Bx( n2 , k2 )。

请注意,muPad 有一个名为“DOM_EXPR”的内置表达式类,它是子类型“_mult”、“_plus”等的超类。例如,a + b 将是“_plus”类型,a * b 将是“_mult”类型“ ETC。

我在课堂上定义的运算之一是乘法。规则如下:

Bx(a, b) * Bx(c, d) = binomial(a, c) * binomial(b, d) / binomial(a+c, b+d) * Bx(a+c, b+d)

这现在在我的代码中完美运行,只要被相乘的两个对象之一属于“Bx”类。例如:

Input:   Bx(2, 1)*Bx(4, 2)
Output:  (3*Bx(6, 3))/5

Input:   2*y*Bx(2, 1)*Bx(4, 2)^2
Output:  ((4*y)/7)*Bx(10, 5)

问题出现如下。每当我将“Bx”类的两个对象相乘时,输出将属于不同的类,称为“DOM_EXPR”,类型为“_mult”。上面的输出就是一个很好的例子。这是有道理的;3/5*Bx(6, 3) 是一个表达式,由“DOM_RAT”和“Bx”类的对象组成,(4*y)/7*Bx(10, 5) 由“DOM_RAT”、“DOM_IDENT”组成”和“Bx”。

如果我将这样的表达式与纯“Bx”相乘,例如:

a:=6*Bx(5,4); => n.b. type is "_mult"
b:=Bx(4,3);   => n.b. type is "Bx"
c:=a*b

然后我得到输出: (10*Bx(9, 7))/3 正如预期的那样。这是因为在“Bx”类的 _mult 操作定义中,我已经定义了“Bx”对象与“_mult”类型“DOM_EXPR”对象相乘时的行为方式。

但是,有时可能会出现两个“Bx”对象都作为“DOM_EXPR”对象的一部分出现的情况。下面的一个例子:

a:=6*Bx(5,4); => n.b. type is "_mult"
b:=3*Bx(4,3); => n.b. type is "_mult"
c:=a*b

现在输出看起来像: (3*Bx(4, 3))*(6*Bx(5, 4))

这不是我想要的。我希望 muPad 进一步评估这个表达式。如果我将参数的所有操作数与现有代码相乘,我会得到:

Input:   6*Bx(5,4)*3*Bx(4,3)
Output:  10*Bx(9, 7)

这是正确的,也是我希望 muPad 在上面将 a 和 b 相乘时做的事情。

对于如何纠正我的代码以使其行为正确的任何见解,我将非常感激。我不一定要寻找语法,但也许更多的是您,一个经验丰富的 OOP 程序员,可能如何实现我正在尝试做的事情,以及它与我正在做的事情有何不同。一旦我了解了我的方法有什么问题以及如何改进它,我就可以自己弄清楚语法。

我在下面粘贴了完整的 muPad 代码。您可以在 matlab 中运行它,只需在命令窗口中键入 mupadwelcome,打开一个新的 mupad 笔记本并将各个代码块粘贴到新行中。

Bx := newDomain("Bx"):
Bx::new := proc(n,k)
begin

//++++//
if args(0)<>2 then
error("There must be exactly two arguments")
end_if;

//----//
new(dom,n,k)

end_proc:

------------------------------------

Bx::print := proc(x)
begin

//++++//
"Bx(".expr2text(op(x,1),op(x,2)).")";

end_proc:

------------------------------------

Bx::_mult := proc(a,b)
local type1,type2,berns,c,berns1,c1,berns2,c2,n,k,ni,ki;
begin

//++++//
if select(args(),testtype,"_mult") = null()

then
lists := split(args(),testtype,Bx);
berns := [lists[1]];
c := _mult(lists[2]);
ni := [op(berns[1])][1];
ki := [op(berns[1])][2];

//----//
if nops(berns) >= 2 and [op(berns)][1] <> [op([op(berns)][1])][1]
then
delete berns[1];
coefficient:=1;

//
while nops(berns)>=1
do
n := op(berns[1],1);
k := op(berns[1],2);
prod := Bx(_plus(ni,n),_plus(ki,k));
coefficient := coefficient*binomial(n,k)*binomial(ni,ki)/binomial(_plus(n,ni),_plus(k,ki));
delete berns[1];
ni := op(prod,1);
ki := op(prod,2);
end_while;
//

c := _mult(coefficient,c);
case c
of 1 do Bx(ni,ki); break;
otherwise freeze(_mult)(c,dom(ni,ki));
end_case;

else
case c
of 1 do berns[1]; break;
otherwise freeze(_mult)(c,berns[1]);
end_case;

end_if;
//----//

//++++//
else
lists := split(args(),testtype,"_mult");
_mult(op(lists[1]),lists[2],lists[3])

end_if;
//++++//

end_proc:

------------------------------------

Bx::_power := proc(a,b)
local res;
begin

//++++//
case b
of 0 do 1; break;
of 1 do a; break;
otherwise
res:=a;

//----//
for i from 1 to b-1 do
res:=res*a;
end_for;
//----//

res;

end_case;
//++++//

end_proc:


a:=6*Bx(5,4)

b:=3*Bx(4,3)

6*Bx(5,4)*3*Bx(4,3)

编辑:有趣的是,如果我没有定义自己的 _mult 和 _power 方法,那么当两个包含“Bx”的 mult 对象相乘时,muPad 似乎会做我想做的事,但显然实际的“Bx”乘法除外,见下图。

mupad 截图

4

0 回答 0