如何使用位运算来代替模和除法运算
How to use bit operations to replace modulu and division operators?
我有这行代码:
base_num = (arr[j]/base)%256;
这一行在循环中运行,操作"/"answers"%"需要大量的资源和时间来执行。我想更改这一行并应用位操作,以最大限度地提高程序性能。我该怎么做?
谢谢。
如果基数是2的n次方,则可以用向右移位n来代替除以。然后,由于取整数的模256相当于取其最后8位,因此可以将其与0xFF进行"与"运算。或者,如果用256*基数进行"与"运算,然后将n右移,则可以反转运算。
base_num = arr[j] >> n;
base_num &= 0xFF;
当然,任何一个半吊子的编译器都应该能够为您做到这一点。
将-O1
或更高版本添加到编译器选项中,编译器将为您执行此操作。
在gcc中,-O1
打开-ftree-slsr
,根据文档,CCD_3是
对树执行直线强度降低。这可以识别涉及乘法的相关表达式,并在可能的情况下用成本较低的计算来替换它们。
这将替换模,如果它是常数,则替换基数。然而,如果您知道基数将是某个非恒定的二次方,那么您可以重构周围的代码,以获得该数字的log2
和减去1的>>
。
您也可以将base_num
声明为8位整数:
#include <stdint.h>
uint8_t base_num;
uint16_t crap;
crap = 0xFF00;
base_num = crap;
如果您的编译器是标准的complement,它将把byte(0xFF00)
(0x00
)的值放入base_num
中。
我还没有遇到一个编译器用纯C(既不是C++也不是C#)进行饱和运算,但如果它这样做了,它会把大于0xFF
的sat_byte(0xFF00)
的值放进base_num
。
请记住,在这种情况下,编译器会警告您精度的损失。在这种情况下,编译器可能会出错(Visual Studio在Treat Warnings as Errors
打开时会出错)。如果发生这种情况,你可以做:
base_num = (uint8_t)crap;
但这似乎是你试图避免的。
你试图做的似乎是删除模运算符,因为这需要除法,而除法是最昂贵的基本算术运算。我通常不会认为这是一个瓶颈,因为任何"智能"编译器(即使在调试模式下)都会将其"优化"为:
base_num = crap & 0xFF;
在一个受支持的平台上(我听说过的每一个主流处理器——x86、AMD64、ARM、MIPS),应该是任何一个。如果听到一个处理器没有基本的AND和OR运算指令,我会目瞪口呆。
- 使用C++中的模板和运算符重载执行矩阵运算
- GCC本机矩阵运算库
- 位阵列上的快速AND运算
- 字符串中int的加法运算
- 在除法中不需要四舍五入
- 算术运算的结果类似于:C浮点变量中的1/3
- 如何使用OpenMP并行化此矩阵时间矢量运算
- 如何在两个 boost::multi_arrays (C++) 之间执行数学运算?
- 在TFHE(完全快速同态加密)上执行除法
- 使用 int 表示浮点除法 C++
- 而循环:简单的除法程序输出零,不明白为什么
- 余数除法和不允许除以零 (c++) 时遇到问题
- 如何在 vtk Poly 数据上进行布尔运算?
- MSVC 无法根据模板参数进行数学运算,这是一个错误吗?
- 避免指针运算,修复叮当整齐错误
- 如何确定涉及 C++ 中除法的算术表达式的数据类型
- 如何使用位运算来代替模和除法运算
- 如何在C++中对大数据整数进行加法、求和、乘法和除法运算
- 为什么在C和C++中没有浮点/双精度的除法余数运算
- 在C++中对存储为字符串的非常大的整数进行除法运算