我一直在使用 Godbolt 编译器并输入以下代码:
constexpr int func(int x)
{
return x > 3 ? x * 2 : (x < -4 ? x - 4 : x / 2);
}
int main(int argc)
{
return func(argc);
}
Run Code Online (Sandbox Code Playgroud)
代码有点简单。这里重要的部分是里面最后除以2 func(int x)。由于 x 是一个整数,基本上任何编译器都会将其简化为移位以避免除法指令。
x86-64 gcc 12.2(对于 Linux,因此 System V ABI)的程序集-O3如下所示:
main:
cmp edi, 3
jle .L2
lea eax, [rdi+rdi]
ret
.L2:
cmp edi, -4
jge .L4
lea eax, [rdi-4]
ret
.L4:
mov eax, edi
mov ecx, 2
cdq
idiv …Run Code Online (Sandbox Code Playgroud) c++ g++ integer-division compiler-optimization constexpr-function
我对使用//或floordiv的整数除法的性质感到困惑,并在python中使用负数.
>>> -5 // 2
-3
>>> int(-5/2)
-2
Run Code Online (Sandbox Code Playgroud)
为什么floordiv()会下降到-3?我认为整数除法应该简单地丢弃(或缺少)小数点后的信息.
我正在研究一个没有硬件分区的Cortex M0 cpu,所以每次分割一些东西时,都会使用GCC库函数.现在,我做的最多的除法之一就是除以256,将短路转换为字节.有没有什么方法可以比默认的GCC库更有效地(比如通过位移)做到这一点?
如果我将150除以100,我应该得到1.5.但是当我像下面那样划分时,我得到1.0:
double result = 150 / 100;
Run Code Online (Sandbox Code Playgroud)
谁能告诉我如何获得1.5?
正如我们所知的计算整数x/2,我们只是y=x/2;为x*2 编写类似的东西; 但优秀的程序员使用位操作来计算它.
他们只是这样做 y = x >> 1;
这两种方法有什么区别吗?差异,我的意思是所需的时间/空间/内存的差异或两者完全相同(即x/2由x >> 1实现)?
也是乘法/除法与其他数字而不是2实现相同的方式(即5*5 = 10*2 + 5*1 = 10 << 1 + 5 = 25)?
cout << -1/2求值为0-1/2评估为-1.为什么会这样?
我做了一个函数来计算atan2(y,x)的定点近似.问题在于运行整个函数所需的~83个循环,70个循环(在AMD FX-6100上使用gcc 4.9.1 mingw-w64 -O3进行编译)完全由一个简单的64位整数除法完成!遗憾的是,该分裂的任何条款都不变.我能加速分裂吗?有什么方法可以删除它吗?
我想我需要这个除法,因为我用1D查找表近似atan2(y,x)我需要将x,y表示的点的距离标准化为单位圆或单位正方形(我选择了一个单位')菱形'是一个旋转45°的单位正方形,在正象限上提供非常均匀的精度).所以除法找到(| y | - | x |)/(| y | + | x |).注意,除数是32位,而分子是32位数,右移29位,因此除法的结果有29个小数位.同样使用浮点除法不是一个选项,因为此函数不需要使用浮点运算.
有任何想法吗?我想不出有什么可以改善这一点(我无法弄清楚为什么只需要一个师就需要70个周期).这是完整的参考功能:
int32_t fpatan2(int32_t y, int32_t x) // does the equivalent of atan2(y, x)/2pi, y and x are integers, not fixed point
{
#include "fpatan.h" // includes the atan LUT as generated by tablegen.exe, the entry bit precision (prec), LUT size power (lutsp) and how many max bits |b-a| takes (abdp)
const uint32_t outfmt = 32; // final output format in s0.outfmt
const …Run Code Online (Sandbox Code Playgroud) 我不怀疑是否需要检查除零.我从来没有听说过负面检查分区!
if( *y == 0 )
return 0; //undefined
else
return *x / *y;
Run Code Online (Sandbox Code Playgroud)
x, y指向int32_t,我在相关的情况下包括这个细节.
在运行时,如果*x==0x80000000, *y==0xffffffff,我得到错误(在Xcode中):
EXC_ARITHMETIC(代码= EXC_I386_DIV,子代码= 0x0)
我在网上找到的所有建议都是除零,但正如你从上面的检查中看到的,我可以从调试窗口看到,这不是这里的情况.
错误意味着什么,我该如何解决?
在ghci我得到以下内容:
?> -1 `div` 2
0
Run Code Online (Sandbox Code Playgroud)
然而:
?> map (`div` 2) [-1]
[-1]
Run Code Online (Sandbox Code Playgroud)
我在使用函数时出现了问题divPair:
divPair :: (Int, Int) -> Int -> (Int, Int)
divPair (a, b) n = (a `div` n, b `div` n)
?> divPair (-1, -2) 2
(-1,-1)
Run Code Online (Sandbox Code Playgroud)
这对我来说真的是一个惊喜,因为我预计它会产生(0, -1).
这里发生了什么?我想我div在Haskell中并没有真正了解一些事情.
在Java中,如果我们划分bytes,shorts或ints,我们总是得到一个int.如果其中一个操作数是long,我们就会得到long.
我的问题是 - 为什么byte或short除法不产生byte或short?为什么总是int?
显然我不是在寻找"因为JLS这么说"的答案,我在Java语言中询问这个设计决策的技术原理.
考虑以下代码示例:
byte byteA = 127;
byte byteB = -128;
short shortA = 32767;
short shortB = -32768;
int intA = 2147483647;
int intB = - -2147483648;
long longA = 9223372036854775807L;
long longB = -9223372036854775808L;
int byteAByteB = byteA/byteB;
int byteAShortB = byteA/shortB;
int byteAIntB = byteA/intB;
long byteALongB = byteA/longB;
int shortAByteB = …Run Code Online (Sandbox Code Playgroud) integer-division ×10
c++ ×4
c ×2
division ×2
python ×2
c# ×1
c99 ×1
embedded ×1
fixed-point ×1
g++ ×1
gcc ×1
haskell ×1
integer ×1
java ×1
optimization ×1
python-2.x ×1
xcode ×1