哪个更快,5+5+5+5+5还是5*5?

3

我不知道怎么问,但是想问一下。请帮忙打标签。顺便说一下,我的朋友问了我一个问题,就是在Java中哪个更快。

int a = 5 + 5 + 5 + 5 + 5

或者

int b = 5 * 5 ?

这与语言有关吗?我的意思是,在Java中,ab快,但在C中不是。

我的答案是ab更快,因为涉及到计算机组织中的加法/乘法比较。


7
我认为在这里衡量性能会很困难,这很大程度上取决于你(或JIT)使用的优化设置,而且可能还取决于底层的硬件。特别是,我预计你示例中的常数情况都将在编译时被编译器优化为25。 - Rup
8个回答

14

这是平台(以及编译器)相关的。如果需要知道,请进行测量。很少有情况需要你必须知道。

然而,在您的两个示例中,它们将在编译时评估(因此不需要运行时计算)。请参见例如http://en.wikipedia.org/wiki/Constant_folding


我只是从理论上回答这个问题,加法是好的。对于它来说,测量不是问题。如果是5+5+....+5呢? - user467871
@hilalпјҡйҰ–е…ҲпјҢдҪ дёҚиғҪеңЁд»Јз Ғдёӯз”Ё 5 + 5 + 5 + ... + 5 зҡ„ж–№ејҸжқҘиЎЁзӨә 5nпјҢйҷӨйқһдҪ дҪҝз”ЁеҫӘзҺҜгҖӮеҚідҪҝиҝҷж ·пјҢжҲ‘и®ӨдёәдёҖдәӣзј–иҜ‘еҷЁд№ҹдјҡе°ҶеҫӘзҺҜиҝӣиЎҢдјҳеҢ–гҖӮ - BoltClock
@BoltClock 是的,有些编译器甚至不会生成循环代码,如果它根本没有任何可观察的副作用 xD - fortran

13
在你的情况下,它不会改变任何东西。让我们编译:
public class Toto {
    public static void main(String[] args) {
        int a = 5 + 5 + 5 + 5 + 5;
        int b = 5 * 5;
    }
}

并检查反编译结果:

public class Toto
{
    public static void main(String args[])
    {
        byte byte0 = 25;
        byte byte1 = 25;
    }
}
编译器已经将所有内容都内联了。

6

这两个都是常量表达式,因此它们将被简化为

int a = 25;
int b = 25;

在编译时(即使是玩具编译器也会这样做,因为这是最简单的优化之一),可以100%确定会进行这些操作的简化。

在极少数情况下,如果这些操作没有被简化,假设有一个JIT将乘法和加法操作码与它们的CPU指令对应起来,那么在大多数现代架构中,所有整数算术操作通常需要相同数量的周期,所以乘一次比加四次要快(刚刚检查过,加法仍然比乘法稍快:1个时钟周期与3个时钟周期,因此在这里使用乘法仍然更好)。

即使在超标量体系结构中,每个周期可以发出多个指令,加法操作的链仍然具有数据依赖性,因此它们必须按顺序执行(并且由于加法指令只需1个时钟周期,因此无法进行管道重叠,仍需要4个时钟周期)。

在大多数CPU架构中,最佳指令序列可能是将原始值左移两个位置,然后加上原始值(5<<2+5)。


我不这么认为。它们不能相等。 - user467871
8
幸运的是,现实并不在乎你喜不喜欢。 - fortran
1
我不是在谈论形而上学。在这种情况下,阅读一本书并了解发生的事情非常简单。 - fortran
这只是在引出一个问题,那个编译速度更快。或者也许不是。 - mob

4
这里至少有两个问题:底层操作的性能和编译器(Java字节码编译器和JIT编译器)的作用。首先是“原始”操作的问题。一般来说,在许多处理器上,加法、减法和乘法所需的时间大致相同。你可能会想象乘法要慢得多,但实际情况并非如此。例如,看看这篇 论文,给出了各种处理器上X86指令的实验计时。从总体上看,乘法稍微比较“慢”,因为它具有更高的延迟。实际上,如果处理器只执行不同数据的一系列乘法操作,那么它将比执行一系列不同数据的加法操作稍微慢一些。但是,只要周围还有其他指令可以在“乘法结束时执行”,那么加法和乘法之间的差异就不会太大。
我之前列出了一份浮点指令在32位Pentium上的时间表(来自Hotspot)(这些数字最初来自Intel的处理器手册,并且我记得我实际测试过这些时间)。请注意,有一个非常相似的模式:加法、减法和乘法基本上需要同样的时间;除法明显较慢。
然后,如果您查看我刚提到的页面上的表格,您会发现2的幂次方除法更快,因为JIT编译器可以将其转换为乘法。 2的幂次方可以在浮点表示中精确表示,因此,如果您用2的幂次方x代替x的除法,则不会失去精度。
换句话说,Java编译器和JIT编译器都可以应用各种优化,这意味着给定代码的底层指令不一定是您想要的。正如其他人所提到的,一个非常基本的优化是预先计算值,因此,如果您写“5 + 5 + 5 + 5 + 5”,实际上Java编译器应该将其替换为“25”。

1
我们应该比较时间复杂度。这个函数是f1(n) = n * c,相当于f2(n) = Sum[1->n] c
乘法的复杂度为O(1)(常数时间,对于任何n都只需要一次计算),加法的复杂度为O(n)(线性时间,加法的次数等于n)。

n不变,它仍然是O(1)。5+5+5和5*3。 - user467871
@hilal - 改编了函数但结果仍然相同。乘法的时间复杂度为O(1),加法的时间复杂度为O(n)(通常情况下)。 - Andreas Dolk

1

这完全取决于您使用的环境:

  • 使用哪个编译器?如果是好的编译器,它会将其编译为常量。

  • 程序代码的其余部分是什么?如果结果未被使用,则编译为NOP(无操作)。

  • 运行在哪种硬件上?如果您有一个针对乘法而不是加法进行超级优化的处理器,理论上乘法可能比加法更快。

  • 等等。

在大多数情况下,您不应该关心什么更快,大多数编译器比您聪明,并将为您进行优化。

如果您真的很在意,那么您可能不会在这里提问,但在这种情况下:进行基准测试。创建两个程序A和B,在典型的实际场景中同时使用它们,测量您感兴趣的时间/能量/其他参数,根据结果决定哪个程序更适合您的需求。


0

这取决于编译器,因为每个编译器都有不同的机制,有些使用左移操作,有些使用其他机制。

但在许多情况下,加法比乘法更快。


-1

我猜加法比乘法快,因为(据我所知)所有的乘法都被视为加法。

补充:

阅读这里以获取一些解释。


2
在大多数现代平台上,都有硬件乘法器。即使是像PIC微控制器这样简单的设备也经常拥有它。 - Oliver Charlesworth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接