这个数字是2的幂吗?

时间:2016-10-12 17:07:58

标签: algorithm binary

我有一个数字(在10中),表示为一个最多10 ^ 6位的字符串。我想检查这个数字是否是2的幂。我能想到的一件事是对指数进行二分搜索并使用FFT和快速求幂算法,但编码时间长且复杂。设n表示输入的长度(即输入中的小数位数)。作为n?

的函数,解决这个问题的最有效算法是什么

3 个答案:

答案 0 :(得分:3)

对于任何给定大小的十进制数,有两个或三个2的幂,并且很容易猜出它们是什么,因为十进制数的大小是其基数10对数的良好近似值,并且您可以通过乘以适当的常数(log 2 10)来计算基数2的对数。因此二元搜索效率低下且不必要。

一旦你有一个试验指数,它将是三百万的量级,你可以使用平方取幂算法和大约22个bugnum十进制乘法。 (最多21次加倍,但这些相对容易。)

根据您执行此检查的频率,您可能希望投资快速bignum代码。但如果不经常,简单的乘法应该没问题。

如果你不希望这些数字是2的幂,你可以先做一个快速计算mod 10 9 ,看看最后9位是否匹配。这将消除所有随机数的百分比。或者,对于更快但稍弱的滤波器,使用64位算术检查最后20位数可以被2 20 整除,而不是10。

答案 1 :(得分:1)

这是一个简单的概率解决方案。

说出您的号码为 // setup an abstract state for the tabs directive .state('tab', { url: '/tab', abstract: true, templateUrl: 'templates/tabs.html', }) // Each tab has its own nav history stack: .state('tab.trips', { url: '/trips', views: { 'tab-trips': { templateUrl: 'templates/trips.html', controller: 'TripsCtrl', } } }) .state('tab.trip-detail', { url: '/trips/:tripId', views: { 'tab-trips': { templateUrl: 'templates/trip-detail.html', controller: 'DestinationCtrl', } } }) ,我们希望找到nk。显然,n = 2^k。我们可以估算k = log2(n) = log10(n) * log2(10)并找出log10(n) ~ len(n)但有一个小错误(例如,k' = len(n) * log2(10),我没有检查,但这应该足够了)。在任何可以想到的解决方案中你可能都需要这个部分,在其他答案中也提到过。

现在让我们检查某些已知|k - k'| <= 5的{​​{1}}。从2到n = 2^k选择一个随机素数k。如果余数不相等,则P绝对不匹配。但如果他们是平等的呢?我声称误报率受k^2的限制。

为什么会这样?因为k然后2 log(k)/kn = 2^k (mod P)。数字D的长度大约为P(因为D = n-2^kk由于第一部分而具有相似的大小),因此不能超过n个不同的素数除数。大约2^k素数小于k,因此您随机选择k^2 / log(k^2)的素数除数的概率小于k^2

在实践中,素数高达10 ^ 9(甚至高达D)就足够了,但你必须做更深入的分析来证明概率。

这个解决方案根本不需要任何长算术,所有计算都可以用64位整数进行。

P.S。为了从1到T选择随机素数,您可以使用以下逻辑:从1到T选择一个随机数并将其递增1直到它为素数。在这种情况下,素数的分布不均匀,前者的分析并不完全正确,但它也可以适应这种随机性。

答案 2 :(得分:0)

我不确定它是否易于应用,但我会按以下方式进行:

1)以二进制显示数字。现在,如果数字是2的幂,它看起来像:

1000000....

只有一个1,其余为0。检查这个号码很容易。现在的问题是如何存储号码。例如,它可能有前导零,这将加强对1:

的搜索

...000010000....

如果只有少量前导零,只需从左到右搜索。如果零的数量未知,我们将不得不......

2)二元搜索1:

2a)在中间切开。

2b)如果两者或两者都不为0(希望你能在合理的时间内检查数字是否为零),则停止并返回false。 (假=不是2的力量)

否则继续使用非零部分。

如果非零部分= 1则停止并返回true。

估计:如果数字是n位(十进制),则其2 ^ n位数为二进制。 二进制搜索需要O(log t),并且由于t = 2 ^ n,log t = n。因此算法应该采用O(n)

假设:

1)您可以访问该号码的二进制视图。

2)您可以在合理的时间内将数字与零进行比较。