我很确定这是解决此问题的合适站点,但是如果适合的话,可以随时将其移至其他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.
Run Code Online (Sandbox Code Playgroud)
特别是,最有效的方法是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每个术语“分开” 。这里的用例是一个符号系统。实际上,我正在尝试修复.as_numer_denom()在SymPy计算机代数系统中调用的函数,该函数目前可通过这种方式简单地进行计算。请参阅相应的SymPy问题。
划分事物有一些问题,我想避免。首先,不能保证一切都会取消。这是因为从数学上讲,(a*b)**n != a**n*b**n通常(如果a和b为正,则成立,但例如,如果a == b ==-1和n == 1/2,则得到(a*b)**n == 1**(1/2) == 1but (-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
Run Code Online (Sandbox Code Playgroud)
但是,这是第一个错误和第二可能永远是一个问题(我认为),因为1/2会被分成1并2通过获取每个学期的分子和分母的算法。
尽管如此,我仍然想知道如何做到这一点而又不di从每个术语中“除掉” ,以便我可以有一个有效的算法来对有理函数求和。
n我不会一次性将商相加,而是使用商的两两相加。
如果部分和抵消,则数字或多项式保持较小,这使得计算速度更快。
您可以避免多次计算相同产品的问题。
您可以尝试以某种方式对加法进行排序,以使取消更有可能(也许先加上小分母的商?),但我不知道这是否值得。
\n\n如果您从头开始,这更容易实现,但我不确定它是否适合替代 SymPy 中有问题的例程。
\n\n编辑:为了使其更明确,我建议计算a1/d1 + a2/d2 + \xe2\x80\xa6 + an/dn为(\xe2\x80\xa6(a1/d1 + a2/d2) + \xe2\x80\xa6 ) + an/dn。