如果我有一个整数n,我怎样才能找到的下一个号码k > n,使得k = 2^i,其中一些i的元件N由按位移动或逻辑.
示例:如果我有n = 123,我怎么能找到k = 128,哪个是2的幂,而不是124哪个只能被2整除.这应该很简单,但它让我望而却步.
据我所知道的,唯一的区别__asm { ... };,并__asm__("...");是第一个使用mov eax, var第二个使用movl %0, %%eax与:"=r" (var)结尾.还有什么其他差异?那又怎么样asm?
我有一个64位无符号整数,正好设置了1位.我想为每个可能的64个值分配一个值(在这种情况下,奇数素数,因此0x1对应于3,0x2对应于5,...,0x8000000000000000对应于313).
似乎最好的方法是转换1 - > 0,2 - > 1,4 - > 2,8 - > 3,...,2 ^ 63 - > 63并查找数组中的值.但即使如此,我也不确定获得二进制指数的最快方法是什么.并且可能还有更快/更好的方法.
此操作将使用10 14到10 16次,因此性能是一个严重的问题.
在汇编编程中,想要从寄存器的低位计算某些东西是相当普遍的,这些位不能保证将其他位置零.在像C这样的高级语言中,你只需将输入转换为小尺寸,让编译器决定是否需要分别将每个输入的高位归零,或者是否可以在输出之后切断结果的高位.事实.
这是为x86-64的(又名AMD64),出于各种原因尤其常见1,其中的一些是存在于其它的ISA.
我将使用64位x86作为示例,但目的是询问/讨论2的补码和无符号二进制算法,因为所有现代CPU都使用它.(注意,C和C++不保证两个补码4,并且有符号溢出是未定义的行为.)
作为示例,考虑一个可以编译为LEA指令2的简单函数.(在X86-64 SysV的(Linux)的ABI 3,前两个函数参数是rdi和rsi,与在返回rax. int是一个32位的类型.)
; int intfunc(int a, int b) { return a + b*4 + 3; }
intfunc:
lea eax, [edi + esi*4 + 3] ; the obvious choice, but gcc can do better
ret
Run Code Online (Sandbox Code Playgroud)
gcc知道即使是负有符号整数,加法也只是从右到左,所以输入的高位不会影响进入的内容eax.因此,它保存了一个指令字节并使用 lea eax, [rdi + rsi*4 + 3]
为什么它有效?
1为什么x86-64频繁出现这种情况:x86-64有可变长度指令,其中额外的前缀字节改变了操作数大小(从32到64或16),因此在指令中通常可以保存一个字节.以相同的速度执行.当写入低8b或16b的寄存器(或稍后读取完整寄存器(Intel pre-IvB)时的失速)时,它也具有错误依赖性(AMD/P4/Silvermont):由于历史原因, …
对于给定的x < 10^15,迅速准确地确定的最大整数p,使得2^p <= x
以下是我尝试过的一些事情:
首先我尝试了这个,但对大数字来说并不准确:
>>> from math import log
>>> x = 2**3
>>> x
8
>>> p = int(log(x, 2))
>>> 2**p == x
True
>>> x = 2**50
>>> p = int(log(x, 2))
>>> 2**p == x #not accurate for large numbers?
False
Run Code Online (Sandbox Code Playgroud)
我可以尝试类似的东西:
p = 1
i = 1
while True:
if i * 2 > n:
break
i *= 2
p += 1
not_p = n - p …Run Code Online (Sandbox Code Playgroud) 可能重复:
计算快速日志基数2上限
在C/C++中将特定整数从十进制转换为二进制时,找出特定整数有多少二进制数字的最快方法是什么?
防爆.47 (10) = 101111 (2)
因此47有六位数以二进制表示.
我试图找到一个数字的二进制基数,比如将数字舍入到它下面的最大整数的floor函数,我想将数字四舍五入到它下面的第一个二进制数.
例如:
for 1000 it should be 512
for 10 it should be 8
for 208 it should be 128
Run Code Online (Sandbox Code Playgroud)
这就是我尝试过的.我觉得日志功能会消耗更多资源,所以有更快的方法吗?
#include<stdio.h>
int main() {
unsigned long long int num;
unsigned long long int mask;
scanf("%llu", &num);
mask = 0x80000000;
while(mask >>= 1) {
if (mask & num)
break;
}
printf("%llu\n", mask);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
谢谢:)