【发布时间】:2011-07-27 07:41:40
【问题描述】:
我很确定这是解决这个问题的正确网站,但如果它更适合那里,请随意将其移至其他一些 stackexchange 网站。
假设您有一个分数之和a1/d1 + a2/d2 + … + an/dn。您想计算一个共同的分子和分母,即将其重写为p/q。我们有公式
p = a1*d2*…*dn + d1*a2*d3*…*dn + … + d1*d2*…d(n-1)*an
q = d1*d2*…*dn.
计算这些东西最有效的方法是什么,尤其是p?你可以看到,如果你天真地计算它,即使用我上面给出的公式,你会计算出很多冗余的东西。例如,您将计算 d1*d2 n-1 次。
我的第一个想法是迭代计算d1*d2、d1*d2*d3、...和dn*d(n-1)、dn*d(n-1)*d(n-2),...但即使这样也是低效的,因为您最终会在“中间”计算两次乘法(例如, 如果n 足够大,您将计算d3*d4 两次)。
我确信这个问题可以用一些图论或组合学以某种方式表达,但我还没有研究足够多的东西来对它有一个很好的感觉。
还有一点:我不关心取消,只是最有效的乘法方式。
更新:
我应该知道 stackoverflow 上的人会假设这些是数字,但我已经习惯了我的用例,所以我忘了提及这一点。
我们不能仅仅从每个术语中“划分”出an。这里的用例是一个符号系统。实际上,我正在尝试在 SymPy computer algebra system 中修复一个名为 .as_numer_denom() 的函数,该函数目前以幼稚的方式计算。请参阅corresponding SymPy issue。
划分事物有一些问题,我想避免这些问题。首先,不能保证事情会取消。这是因为从数学上讲,(a*b)**n != a**n*b**n 通常是(如果a 和b 是正数,则它成立,但例如,如果a == b ==-1 和n == 1/2,你会得到(a*b)**n == 1**(1/2) == 1 但(-1)**(1/2)*(-1)**(1/2) == I*I == -1)。所以我不认为假设除以an 会在表达式中取消它是一个好主意(这实际上可能是没有根据的,我需要检查代码的作用)。
其次,我还想应用这个算法来计算有理函数的总和。在这种情况下,这些项将自动相乘成一个多项式,并且“除”每个an 将涉及应用多项式除法算法。您可以看到,在这种情况下,您确实希望首先计算最有效的乘法。
更新 2:
我认为我对取消象征性术语的担忧可能是没有根据的。 SymPy 不会自动取消像 x**n*x**(m - n) 这样的东西,但我认为任何可以通过乘法组合的指数也可以通过除法组合,所以应该取消幂。
常量自动分布在添加中存在问题,例如:
In [13]: 2*(x + y)*z*(S(1)/2)
Out[13]:
z⋅(2⋅x + 2⋅y)
─────────────
2
但这首先是bug,其次永远不会是问题(我认为),因为1/2 将通过获取每个术语的分子和分母的算法分成1 和2。
尽管如此,我仍然想知道如何在不从每个术语中“划分”di 的情况下做到这一点,以便我可以有一个有效的算法来求和有理函数。
【问题讨论】:
-
a*b在各种数字系统中与b*a不同。但是你必须明确地说在这样的系统中工作,否则每个人都认为你在谈论整数。对于(-1)**(1/2)*(-1)**(1/2) == I*I == -1部分,您必须先阅读一些有关代数和多值“函数”的内容,然后再开始说这些内容。 -
这与交换性无关。但你确实无意中提出了一个好观点。该算法必须与非交换符号一起使用(在这种情况下,只是分开肯定行不通)
-
实际上,我认为这对非交换式甚至没有意义。
-
当你说事物不取消时,你的意思是象征性地,a1*d2*d3*...*dn 不等于 (a1/d1)*d1*d2*d3 *...*dn?如果是这种情况,那么您需要非常明确地描述符号系统的所有规则。你至少有联想吗?而且,如前所述,交换性呢?在这种情况下,“分裂”究竟代表什么?我有点不清楚在这种除法的情况下,您的取幂示例与“取消”有什么关系。
-
另外,这至少在一个非交换上下文中是有意义的。让 a_i 和 d_i 成为矩阵,其中 a_i/d_i 被理解为 a_i 乘以 d_i 的倒数(当然,我们需要 d_i 是可逆的)。然后,一切仍然有意义。这种情况强调需要明确哪些代数规则是有效的,因为这种情况使 templatetypedef 的答案不适用,但 starblue 的答案仍然可以。