找到10小于x的最大功率的最快方法

peo*_*oro 8 language-agnostic algorithm base digits

有没有什么快速的方法可以找到比给定数字小10的最大功率?

我现在正在使用这个算法,但是当我看到它时,我内心的某些东西会消失:

10**( int( math.log10(x) ) ) # python
pow( 10, (int) log10(x) )   // C
Run Code Online (Sandbox Code Playgroud)

我可以用一个循环实现我的问题的简单log10pow函数,但我仍然想知道是否有一些魔术的十进制数.

Ano*_*on. 6

另一种算法是:

i = 1;
while((i * 10) < x)
    i *= 10;
Run Code Online (Sandbox Code Playgroud)

  • 一切都是权衡.对于具有有限范围的数字,O(n)可能很好,并且该选项不使用额外的空间(与具有大的查找表,预先计算一系列正方形等相比).计算复杂性并不是算法是否"好"的全部和最终目的.将它修改为方形而不是天真乘法直到它接近是相对简单的,但这将涉及更多的代码,并且实际上可能在较小的输入上减慢它.正确的选择取决于预期的输入数据,而不仅仅取决于大O性能. (5认同)

Ira*_*ter 5

记录和电源是昂贵的操作.如果你想要快速,你可能想要在表中查找IEEE二进制指数以获得大约10的幂,然后检查尾数是否强制改变+1.这应该是3或4个整数机器指令(或者O(1)具有相当小的常数).

给定表格:

  int IEEE_exponent_to_power_of_ten[2048]; // needs to be 2*max(IEEE_exponent)
  double next_power_of_ten[600]; // needs to be 2*log10(pow(2,1024)]
  // you can compute these tables offline if needed
  for (p=-1023;p>1023;p++) // bounds are rough, see actual IEEE exponent ranges
  {  IEEE_exponent_to_power_of_ten[p+1024]=log10(pow(2,p)); // you might have to worry about roundoff errors here
     next_power_of_ten[log10(pow(2,p))+1024]=pow(10,IEEE_exponent_to_power_of_ten[p+1024]);
  }
Run Code Online (Sandbox Code Playgroud)

那你的计算应该是:

  power_of_ten=IEEE_exponent_to_power_of_10[IEEE_Exponent(x)+1023];
  if (x>=next_power_of_ten[power_of_ten]) power_of_ten++;
  answer=next_power_of_ten[power_of_ten];
Run Code Online (Sandbox Code Playgroud)

[您可能真的需要将其写为汇编程序以挤出每个最后一个时钟.] [此代码未经过测试.]

但是,如果你坚持在python中执行此操作,解释器开销可能会淹没日志/ exp时间,这可能无关紧要.

那么,你想要快速,还是想要短写?

EDIT 12/23:OP现在告诉我们他的"x"是不可或缺的.假设它是64(或32)位整数,我的提议仍然有效,但显然没有"IEEE_Exponent".大多数处理器都有一个"查找第一个"指令,它会告诉您左侧(最重要)部分值的0位数,例如前导零; 你很可能这实际上是64(或32)减去值的2的幂.给定exponent = 64 - leadingzeros,你有两个指数的幂,并且算法的其余部分大部分基本不变(修改留给读者).

如果处理器没有find-first-one指令,那么最好的选择是平衡判别树来确定10的幂.对于64位,这样的树将花费最多18个比较来确定指数(10 ^ 18~2 ^ 64).

  • *记录和电源是昂贵的操作.*在没有硬件支持超越操作的情况下显然就是这种情况.但是,我们谈论消费级通用CPU(现代x86,Power,x86_64 ......)的速度有多慢? (2认同)