求解 x*log(x) 的最快方法

计算科学 数值分析 C++
2021-12-11 22:21:43

进一步来说,Cxlog2(x)K=0,其中是常数(表示对数基数 2)。CKlog2

我正在解决一个 topcoder 问题SortEstimate,这需要我们解决上述方程。(附带问题:它可以称为多项式吗?不能?那么这样的方程的名称是什么?)

我使用二进制搜索在 C++ 中解决了这个问题,并且能够以高精度成功地做到这一点。但后来我遇到了一个相当不同的解决方案,我认为,在大学学习数值分析后,可能正在使用一种方法来求根。我想找到该方法,但在 google 或其他在线可用的数值分析资源上没有找到任何有用的东西。

这是代码——方程中的也是这里的变量Ktime

#include <iostream>
#include <cmath>
using namespace std;
class SortEstimate
{
public:

    double howMany(int c, int time){

    long double x = 7; 
    long double r = double(time)/double(c); 
    for (int i = 0; i<1000; i++) { 
      x = x - (x * log(x)/log(2.0) - r)/(1.0 + log(x)/log(2.0)); 
    } 
    return x; 

  } 
};

int main()
{
    SortEstimate sort;
    cout<<sort.howMany(1,8)<<endl;//4
    cout<<sort.howMany(2,16)<<endl;//4
    cout<<sort.howMany(37,12392342)<<endl;//23105
    cout<<sort.howMany(1,2000000000)<<endl;//7.6375e+07

    return 0;
}

for循环中,语句是什么意思?我能想到的就是它应该是一种数值方法。任何信息都会很有用。

如果这不是提出这个疑问的正确社区,那么请向我推荐正确的社区。

1个回答

这个方程不是多项式的。假设都是正数(如在您的链接问题中),则的解可以根据Lambert函数Wright函数找到:KCCxln2(x)K=0Wω

x=DW0(D)=Dω(ln(D))

其中D=ln(2)K/C

Corless 等人。1996 年是实施 Lambert的一个很好的参考。您可以在此处找到一些基本的 Matlab 代码来对其进行数值计算,将其转换为 C++ 应该很简单。通过使用级数和渐近扩展来找到更好的初始猜测,可以提高此代码的性能。W

至于您问题中的 C++ 代码在做什么,它似乎只不过是牛顿方法的天真实现。for循环只是多次迭代递归关系。它假设系统将在 1,000 步后收敛。这可能是一个合理的假设,但效率很低。我链接到的 Matlab 代码使用高阶方案、哈雷方法和基于容差的收敛条件。