【问题标题】:Fastest algorithm to find the largest n such that x^n<=y找到最大 n 的最快算法,使得 x^n<=y
【发布时间】:2017-07-24 13:26:54
【问题描述】:

我正在做一个项目,该项目需要我找到最大的 n,使得 x^n

约束:

x>=1 & y>=1

使用我想到的第一种方法,当 x=12 和 y = 411^20000 时,我花了大约 5 秒找到 n,即,

int n=0;
int x=12;
int y=100;
int temp;
int answer;
while(1)
{
    temp = pow(x,n);
    if(temp>y)
        {
            answer = n-1;
            return(0);
        }
   n++;
}

注意:不是实际代码。不想让 gmp 语法复杂化

有更快的算法吗? 完整代码: https://pastebin.com/J1vbmEbK

【问题讨论】:

  • 好吧,即使你不想发布完整的代码,我们仍然需要算法。
  • 一点改进是迭代乘法而不是计算每个幂
  • 即使你发布伪代码,也请尽量使用像exp这样的真实函数,而不是按位异或运算符。
  • 我可能不明白你的问题的限制,但为什么不直接计算答案,floor( log(y)/log(x) )? log(y)/log(x) 是计算 log-base-x(y) 的方式,其中 log 只是自然对数(或任何方便的对数)。
  • 顺便说一句,在您的伪代码中,n 是不变的。

标签: c algorithm math gmp


【解决方案1】:

如果gmp library包含对数函数,使用它

result = Floor(log(y)/log(x))

否则你可以尽可能地利用binary search - square x (x, x^2, x^4, x^8),然后减少功率步骤

用普通数字检查的快速而肮脏的实现

returns 24 for x = 2; y = 31415926.0;
(same as Floor(ln(y)/ln(x))

int FindXPower(double x, double y) 
{
  int Powers[64];
  double t, s, next;
  int ix;

  //exponential search phase
  ix = 0;
  t = x;
  while (t <= y)
  {
    Powers[ix++] = t;  //remember them to use later
    t = t * t;
  };
  //now powers contain [x,x^2,x^4,x^8,x^16...]

  ix--;
  int Result = 1 << ix;  // 2^lastindex: 1,2,4,8,16,32...

  //binary search phase
  s = Powers[ix--];     //max value after squaring
  while ((s < y) && (ix >= 0))
  {
     t = Powers[ix];
     next = s * t;
     while (next < y)
     {
      s = next;
      next = next * t;
      Result = Result + (1<<ix);
     }
     ix--;
  };
  return Result;
}

【讨论】:

  • gmp 中没有对数函数。该死,我想哭。
  • 这个 repo 应该包含一个允许你计算日志的 GMP 扩展。 github.com/linas/anant 。不过,我仍然会选择二进制搜索方法。
  • @DavideSpataro 为什么你更喜欢二进制搜索而不是日志方法?
  • 除以y._mp_size / x._mp_size,大致相当于log256。
  • @AkiSuihkonen:非常粗略。更准确的估计是(mpz_sizeinbase(y, 2)-1)/mpz_sizeinbase(x,2)。
【解决方案2】:

您可以通过二分法搜索正确的值,而不是线性递减n。

定义两个变量:n_low 和 n_high,不变量在任何时刻x^n_high 严格大于y 和x^n_low 小于或等于y。

在每次迭代中,计算m 的值,它将n_high 和n_low 之间的距离减半。

然后将x^m 与y 进行比较。如果严格大于,则分配:n_high = m 否则分配n_low = m。当n_low+1==n_high n_low 的值是您要查找的值时。

【讨论】:

  • n 是线性递增的,如果你将二分法的最大间隔的值设置为 y,我不确定你会不会那么快。
  • 我想我会坚持使用 MBo 答案中的二进制搜索方法。
  • @rjpj1998 是一样的 ;)
  • 伙计,对不起。我应该意识到的。这样的算法对我来说是新的,它看起来非常令人生畏哈哈。
  • @rjpj1998 没问题,MBo方案更好解释
【解决方案3】:

我假设您正在使用任意精度的整数(GMP 还支持任意精度的浮点数)。

  • 将 bigint 转换为浮点数。这会导致舍入错误。
  • 估计计算n_est = floor(log(y_float) / log(x_float))的结果。
  • 实际的n 是n_est - 1、n_est 或n_est + 1,可以轻松检查。

【讨论】:

    猜你喜欢
    • 2023-02-10
    • 2019-02-07
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-18
    • 1970-01-01
    相关资源
    最近更新 更多