我可以假设按位AND操作是O(1)吗?如果是这样的话?

时间:2016-04-25 01:24:34

标签: algorithm time-complexity big-o bitwise-and

我的处理器只能对8位或16位无符号整数进行算术运算。

1)这意味着此处理器的字长为16位,是否正确?

单词的操作是O(1)。

这个原因与处理器工作原理的实际电路级实现有关,对吗?

如果我要添加两个单词,结果是一个超过16位的数字,我可以说明以下内容吗?

1)处理器可以添加数字,但只报告16个最低有效数字。

2)为了报告超过16位,处理器必须具有允许这些操作大量的软件(数字不适合单词)。

最后,

假设我有一个单词w是一个16位数字,我想要八个最低有效数字。我可以做w& 0xFF的。这次行动的时间复杂度是多少?这是O(1),因为处理器的电路级实现也是如此?

4 个答案:

答案 0 :(得分:3)

首先关于添加。大多数CPU在某些处理器状态寄存器中具有所谓的进位标志,可以检测到溢出寄存器位大小的加法和减法。因此,找出特定CPU上的寄存器大小以确定数据总线带宽,然后了解如何检查状态寄存器标志。大多数CPU都有SUB&为此目的添加和不携带。

接下来,关于时间复杂度:您不能假设为此使用Big O表示法。您需要找出CPU在绝对时间内执行操作所需的周期(频率*周期),然后您需要考虑其他内容,如内存访问与L1和L2缓存访问,以确定操作的总时间将占用该CPU。

最后,从汇编代码中访问内存(正如您所暗示的那样)让您比使用Python等高阶语言更有效率。 CPU将包含可以调整其内存寻址以适合您要查找的大小的指令。类C语言也将在语言中具备这种能力,但Python不会。 JavaScript甚至没有整数但我离题......

如果您的目标是了解低级编程,那么总能让您更好地理解机器,尤其是指针和调试,我鼓励您在Arduino上进行视频课程。你甚至可以享受它并开始一个新的爱好。

答案 1 :(得分:3)

你显然对O(...)的含义有些困惑。

  1. big-O表示法需要变量;例如,使用比较和交换进行排序已知 n 元素数组至少为O(n*log(n)),并且您有 n 即变量:as n 增加排序时间也会增加得更快。当说x & 0xFF是O(1)时,您正在谈论的变量是什么?

  2. big-O是关于抽象算法,其中 n 可以增长到无穷大。如果 n 并且计算机受上限限制,那么任何算法都不会终止或受常量限制(讨论某些限制是没有意义的如果 n 无法增加超过特定限制,则 n 会向无穷大方向增加。

  3. 在谈论低级硬件操作时,所有操作都是O(1)。有些更快,只需要一个步骤" (比如清除寄存器),有些需要更多步骤(如整数除法)。然而,即使是除法,也最多需要n个步骤,其中n是一个小整数。

    当讨论具体CPU中不同算法的性能时,使用big-O表示法没有意义,你可以做的是计算完成一个显式公式所需的机器周期数,可能取决于输入大小 n ,但 n 不能增长到无穷大。

    这就是Knuth在TAOCP

    中所做的 PS:不幸的是,今天的CPU非常复杂,以至于循环计数在现实世界中不再起作用。例如,它们可以将指令拆分为重新安排的并行运行的微指令,它们支持具有回溯,分支预测和其他难以分析的技术的推测执行。最重要的是,缓存问题在今天非常重要,不同但兼容的模型可能有很多不同的方法。真正知道用现代CPU执行一段代码需要多长时间的唯一方法就是在特定的CPU模型和硬件上运行和测量实际数据。

答案 2 :(得分:2)

按顺序:

  1. 没有。如果您的处理器可以执行8位或16位操作,则它可以是8位或16位处理器。实际上,它更可能是8位,因为大多数处理器都试图处理双倍大小的操作。

  2. 是的,O(1)。但不是因为它是硬件,而是因为它在硬件中实现了O(1)。另外,请记住,所有O(x)实际上都是“时间常数”。因此,如果某事是O(16),则实际上是O(1)乘以常数16。

  3. 最后,如果你有一个16位字,并且你想要低位,并且你的处理器确实支持8位操作,你可以用MOV指令访问低位。类似的东西:

    mov16 ax, (memory)
    mov8  (othermemory), al
    

    如果那个不可用,你必须做一个AND,那么是,AND将是O(1),因为它几乎肯定是硬件那样的。即使不是,最糟糕的情况可能是O(8),这实际上是O(1)的别名。

答案 3 :(得分:1)

简答:

是的,单个按位AND将被视为O(1)

更多细节:

即使您查看了每个位的操作次数,它仍然是O(1)。实际的位操作数可以根据变量类型而变化,例如, 8位与16位对比32位与64位(甚至128位或更多)。关键是无论底层机器使用什么,它仍然会执行constant个操作来执行它。因此,即使计算机随着时间的推移而发展,按位AND仍然是O(1)

帮助添加澄清的另一个示例

以下代码块是O(1):

print('Hello World');
print('Hello World');
print('Hello World');

虽然我们打印hello world 3次,但每次运行它时,运行和操作都需要一定的时间,如果有人将大数据集输入程序,则不会花费更长的时间。无论输入如何,它只需打印3件事。

在按位AND的情况下,我们执行指定数量的子操作,这些子操作始终是相同的数字。例如8,16,32等用于一次操作,但其始终相同或不变。

在您的示例中,听起来您正试图表明您有一些操作不需要所有位也能执行。即使这些较小的操作只考虑4位,也就是说8.当你的代码命中时,你的代码总是会执行一定数量的操作。它就像打印4个hello world语句而不是8个hello world语句。无论哪种方式,4或8次打印,它仍然是恒定的。

这就是单个按位AND运算为O(1)的原因。