如果我有一个整数n,我怎样才能找到的下一个号码k > n,使得k = 2^i,其中一些i的元件N由按位移动或逻辑.
示例:如果我有n = 123,我怎么能找到k = 128,哪个是2的幂,而不是124哪个只能被2整除.这应该很简单,但它让我望而却步.
我需要找到大于或等于给定值的2的最小幂.到目前为止,我有这个:
int value = 3221; // 3221 is just an example, could be any number
int result = 1;
while (result < value) result <<= 1;
Run Code Online (Sandbox Code Playgroud)
它工作正常,但感觉有点幼稚.这个问题有更好的算法吗?
编辑.有一些很好的Assembler建议,所以我将这些标签添加到问题中.
如果我有一个数字a,我希望x的值在b = 2 ^ x,其中b是2的下一个幂大于a.
如果您错过了标记,那么这是Java,而a是一个int.我正在寻找最快的方法来做到这一点.我的解决方案就是使用bit-twiddling来获取b,然后执行(int)(log(b)/ log(2)),但我觉得必须有一个更快的方法,不涉及划分两个浮动 -点数.
是否有更快的替代以下表达式:
Math.pow(2,Math.floor(Math.log(x)/Math.log(2)))
Run Code Online (Sandbox Code Playgroud)
也就是说,取最接近(较小)的2的整数倍?我在内循环中有这样的表达.我怀疑它可能会快得多,考虑到可以从双尾的IEEE 754表示中获取尾数.
到目前为止我想出了三个解决方案:
极低效的标准库pow和log2功能:
int_fast16_t powlog(uint_fast16_t n)
{
return static_cast<uint_fast16_t>(pow(2, floor(log2(n))));
}
Run Code Online (Sandbox Code Playgroud)
计算后续2次幂的效率要高得多,直到我达到的数量超过我必须达到的数量:
uint_fast16_t multiply(uint_fast16_t n)
{
uint_fast16_t maxpow = 1;
while(2*maxpow <= n)
maxpow *= 2;
return maxpow;
}
Run Code Online (Sandbox Code Playgroud)
到目前为止最有效的binsearching预先计算的2的权力表:
uint_fast16_t binsearch(uint_fast16_t n)
{
static array<uint_fast16_t, 20> pows {1,2,4,8,16,32,64,128,256,512,
1024,2048,4096,8192,16384,32768,65536,131072,262144,524288};
return *(upper_bound(pows.begin(), pows.end(), n)-1);
}
Run Code Online (Sandbox Code Playgroud)
这可以进一步优化吗?可以在这里使用的任何技巧?
我使用的完整基准:
#include <iostream>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <array>
#include <algorithm>
using namespace std;
using namespace chrono;
uint_fast16_t powlog(uint_fast16_t n)
{
return static_cast<uint_fast16_t>(pow(2, floor(log2(n))));
}
uint_fast16_t multiply(uint_fast16_t n)
{ …Run Code Online (Sandbox Code Playgroud) 我要求计算k为2的最小幂,> =整数值,n(n总是> 0)
目前我正在使用:
#define log2(x) log(x)/log(2)
#define round(x) (int)(x+0.5)
k = round(pow(2,(ceil(log2(n)))));
Run Code Online (Sandbox Code Playgroud)
这是一个性能关键的功能
是否有更高计算效率的计算方法k?
我分配了大缓冲区,然后拆分成多个大小的块.这些尺寸从32开始,然后在每次增加时乘以2.
struct Node
{
Node* Next;
void* Data;
const unsigned Size;
};
Node* m_Buffers[16];
Run Code Online (Sandbox Code Playgroud)
这意味着缓冲区m_Buffers[0]的大小为32,缓冲区m_Buffers[1]的大小为64,依此类推.
并且一个函数接受一个数字并返回一个指定数字可以舍入到的大小的缓冲区.
void * GetBuffer(unsigned size)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
例如,如果我请求一个384的缓冲区,那么我需要能够在512处将其舍入并从中返回缓冲区m_Buffers[4].
到目前为止,我正在使用循环来舍入:
void * GetBuffer(unsigned size)
{
unsigned buffer_size = 32;
while (buffer_size < size)
{
buffer_size *= 2;
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
但我很好奇是否有一种更好的方法可以不涉及循环.如果有一种方法可以将舍入数字转换为数组中的索引而不使用switch语句.
说实话,我甚至不确定标题是否正确.所以我为此道歉.
我需要一个可以在编译时进行评估的宏,例如:
#define FIND_RANGE(x) \
if x>16 \
32 \
elif x>8 \
16 \
elif x>4 \
8 \
elif x>2 \
4 \
elif x>1 \
2 \
else \
1 \
endif \
Run Code Online (Sandbox Code Playgroud)
所以代码
#define S1 FIND_RANGE(7)
unsinged int i = S1;
Run Code Online (Sandbox Code Playgroud)
将被发送到编译器
unsinged int i = 8;
Run Code Online (Sandbox Code Playgroud)
是否可以完成这个简单的算法,以便在编译时进行评估?
问题
Given N, return M that satisfy the equation: N + M = 2 * (N ^ M)
Run Code Online (Sandbox Code Playgroud)
约束
1 <= Test Cases = 10^5;
1 <= N <= 10^18
Run Code Online (Sandbox Code Playgroud)
我在其中一项招聘挑战中遇到了这个问题。
通过反复试验的方法,我发现了一种模式 -这样的 M 存在于 N/3 和 3N 之间,并且N + M 是偶数。所以我对它进行了编码,提交后,我的解决方案只能通过一半的测试用例。这不是什么优化,因为这种方法的时间复杂度与蛮力解决方案的时间复杂度相同。
我知道我的解决方案不是最佳解决方案。
这是我的解决方案:
def solve(n):
m = n//3
end = 3*n
# If both m and n are odd/even, their sum will be even
if (m&1 == 1 and n & 1 == 1) or …Run Code Online (Sandbox Code Playgroud) algorithm ×3
c ×3
c++ ×3
optimization ×2
performance ×2
assembly ×1
double ×1
ieee-754 ×1
java ×1
javascript ×1
math ×1
python ×1
rounding ×1
xor ×1