为什么我们总是将常数声明为 2 的幂?
我在其他代码中看到的大多数常量都是 2 的幂, ie
#define SIZE 256
或
public static final int SIZE = 2048;
我们这样做而不是 ie 有什么特殊原因吗
#define SIZE 257
?
Most of the constants I see in others code are powers of 2, i.e.
#define SIZE 256
or
public static final int SIZE = 2048;
Is there any particular reason why we do that instead of i.e.
#define SIZE 257
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
2 的幂很方便,因为它们可以很好地映射到硬件中的底层约束。
例如:
对于标志,2 的幂始终设置一个位。 所以类似
MY_FLAG_1 | MY_FLAG_2 | MY_FLAG_3 | ...
仅适用于 2 的幂。 同样,使用&
测试标志。为缓冲区大小等选择最接近的二的较大幂也是一种惯例。
Powers of 2 are convenient because they map well to underlying constraints in hardware.
Such as:
For flags, powers of 2 always have a single bit set. So things like
MY_FLAG_1 | MY_FLAG_2 | MY_FLAG_3 | ...
only work with powers of two. Likewise for testing for flags with&
.Its also something of a convention to pick the nearest larger power of two for buffer sizes and the like.
一个很好的理由是位掩码。 例如,如果您使用常量来表示对象(或其他任何对象)的属性,则可以通过位掩码将许多属性保存到单个整数中,并稍后识别各个属性。 非常适合在数据库中保存许多“标志”。
One good reason is bitmasking. As an example, if you are using constants to represent attributes of an object (or anything else), you can save many attributes into a single integer through bitmasking, and identify the individual attributes later. Great for saving many "flags" in a database.
内存通常是由操作系统以页面大小的倍数分配的,并且在许多情况下,安排事物以完全适合页面(为了不浪费内存)是有用的。 这是否真的有帮助取决于具体的分配例程; 例如,如果存在隐式标头,则大小为 2 的幂可能实际上会造成伤害。
Memory is typically allocated in multiples of page sizes from the operating system, and in many cases, it is useful to arrange things to fit pages exactly (in order to not waste memory). It depends on the specific allocation routine whether this really helps; e.g. if there is an implicit header, having the size a power of two may actually hurt.
当谈到数组大小时,我怀疑有两个原因可以解释为什么二的幂更受青睐。 其中一个 - 正如这里的几个回复所证明的 - 不知道“幕后”发生了什么的程序员似乎有一种普遍的感觉,即使用 2 的幂可能会更有效。 另一个(现在主要是历史)与循环缓冲区有关。
使用读写索引(或指针)上的掩码可以更轻松、更快速地处理为 2 的幂的循环缓冲区,而不是使用通常较慢的模运算或使用需要分支的条件。 这对于较旧的机器至关重要,但对于传输大量数据仍然很重要 - 例如图形处理
例如,在 C 中,循环缓冲区中可读取的字节数可以通过以下方式获得:
如果不使用 2 的幂那么等效的结果是:
在没有实现除法/模数指令的机器上,小“%”可能需要数百个周期,因此您需要类似的东西:
这会使代码混乱并导致分支,这可能会导致指令管道停顿。
写入缓冲区
(通常)变得更加高效:
当然,如果您使用无符号 8 位变量来索引 256 条目数组,那么您甚至不需要进行屏蔽。
When it comes to array sizes I suspect there are two reasons why powers of two are favoured. One - as evidenced by several replies here - is that programmers who don't know what is going on "under the hood" seem to have a general sense that it might somehow be more efficient to use a power of two. The other is (mostly historical now) to do with cyclic buffers.
Cyclic buffers that are powers of two can be handled more easily and faster using masks can on the read and write indices (or pointers) rather than using the normally slower modulo operation or using conditions that require branches. This was crucial on older machines but can still be important for transferring large amounts data - e.g. graphics processing
For example, in C, the the number of bytes available to be read in a cyclic buffer can be obtained by:
If not using power of two then the equivalent would be:
On machines that don't implement a division/modulus instruction that little "%" could take several hundred cycles, so you would need something like:
Which clutters the code and causes branching which can stall the instruction pipeline.
Writing to the buffer which was something like
becomes the (generally) more efficient:
Of course if you used an unsigned 8 bit variable to index a 256 entry array then you didn't even need to do the masking.
我们的变量大小是 2 的幂(1、2、4 或 8 字节)。 计算机可以轻松地在这些边界上工作。 在过去,我们常常小心地填充结构以使代码运行得更快,有时还可以使指针运算更容易。
如果您可以在 256 和 257 之间进行选择,我们会选择 256。原因之一是为了调试。 当您查看内存或文件时,调试器或十六进制文件查看器将以 2 的幂行显示数据。
这里显示每行 16 个字节,以 4 为一组。
(来源:wikimedia.org)
对于标志,我们将它们设为 2 的幂,这样我们就可以在一个变量中单独处理它们,而不是在多个变量或数组中。
因此它们都可以与同一个变量进行或或运算。
许多程序员会用十六进制而不是十进制编写数字,以便更容易看到各个位的情况。
Our variable sizes are powers of 2 (1, 2, 4, or 8 bytes). The computer is comfortable working on these boundaries. In the old days, we used to carefully pad our structs to make our code go faster, and sometimes to make pointer arithmetic easier.
If you have a choice between a size of 256 and 257, we go with 256. One reason would be for debugging. When you look at memory or in a file, your debugger or hex file viewer will show data in lines that are a power of two.
Here's one that shows 16 bytes per line, in groups of 4.
(source: wikimedia.org)
For flags, we make them powers of two so we can treat them all separately in one variable instead of in many variables or an array.
So they can all be or'd to and and'd from the same variable.
Many programmers will write the numbers in hexadecimal instead of decimal so that it's easier to see what's going on with individual bits.
确实没有太多理由。 由于结构化变量和堆栈上的变量对齐,三个字节的数组可能会占用内存中的 4 或 8 个字节。 我觉得这感觉很好。
由于堆内部结构的开销,从堆中分配全部页面可能无法按预期有效地工作。 分配 4096 字节(32 位 Windows 计算机为 1 页)可能会导致分配 4104 字节或更多。
如果常量是标志,那么情况就大不一样了。 通常,使用位标志比某些不是 2 的幂的基数中的标志更有效。
Not much reason really. Due to alignment of variables in structured and on the stack an array of three bytes will likely take of 4 or 8 bytes in memory. I think it just feels nice.
Allocating a whole number of pages from the heap may not work as effectively as desired due to the overhead of the heap's internal structure. Allocation 4096 bytes (1 page for a 32 bit windows machine) may likely result in an allocation of 4104 bytes or more.
If the constants are flags, then the story is very different. It is typically more efficient to have bit flags than flags in some base that is not a power of 2.
对于二进制计算机,可以方便地使用基于标准的二进制倍数,例如Mebibyte(或 Kibi、Gibi、Tebi ...)。 这些 2 的幂在 八进制 或 十六进制 表示法。
With binary computers, it's convenient to use standards-based binary multiples like Mebibyte (or Kibi, Gibi, Tebi ...). These power of 2 numbers also look nice in Octal or Hex notations.
向存储芯片添加更多位通常是通过将芯片上“单元”的数量增加四倍来完成的。 两倍宽、两倍长、四倍内存(“单元”之间的距离更小除外)。
此外,使用单个移位进行乘法比根据是否设置了特定位来添加连续移位的通用乘法算法更容易。 OpenGL 因需要两种尺寸的纹理才能访问特定扫描线而闻名。
Adding more bits to a memory chip is usually done by quadrupling the number of "cells" on the chip. Twice as wide, twice as long, four times the memory (excepting smaller distances between the "cells").
Also it's easier to multiply using a single shift rather than the generic mulplication algorithm of adding successive shifts depending on if a particular bit is set or not. OpenGL was famous for requiring power of two sizes for textures to access particular scan lines.
因为计算机内存以 0/1 工作,即二进制系统。
Because Computer Memory works with 0/1 that is binary system.