gpt4 book ai didi

java - 为什么按位运算符在比较 boolean 值时比 Java 中的 "normal"慢?

转载 作者:行者123 更新时间:2023-12-02 05:44:29 25 4
gpt4 key购买 nike

假设如下:您有两个函数,它们基本上执行相同的操作,即使用 AND 和 OR 运算符比较两个随机 boolean 值。但第一个函数使用正常的条件运算符 && 和 || 来完成此操作,另一个函数使用按位运算符 & 和 | 来完成此操作。

我认为这两个函数当然需要相同的时间才能完成,但是事实并非如此。使用按位比较的时间比使用“正常”条件运算符的时间多五分之一。

我很困惑,做了一些研究,在 Oracle 的 Java 文档中找到了以下条件运算符的定义:

The && and || operators perform Conditional-AND and Conditional-OR operations on two boolean expressions. These operators exhibit "short-circuiting" behavior, which means that the second operand is evaluated only if needed.
&& Conditional-AND
|| Conditional-OR

对于按位运算符:

The Java programming language also provides operators that perform bitwise and bit shift operations on integral types. 
The bitwise & operator performs a bitwise AND operation.

The bitwise | operator performs a bitwise inclusive OR operation.

嗯,这些定义并没有真正令我满意,我的问题仍然没有得到解答。因此,我做了更多研究,并在 stackoverflow 上发现了一个关于 Java 中按位运算符对 boolean 值的影响的问题( Effect of a Bitwise Operator on a Boolean in Java ),但这也没有真正回答我的问题。

这是我测试它的代码,它使用随机数生成器来获取随机 boolean 值以相互比较并循环多次。

import java.util.Random;

public class Main {

private static final long LOOPS = 100000000L;
private static Random rng = new Random();

public static final void main(String[] args)
{
System.out.println("Bitwise operator: "+loopWithBitwiseOperator(LOOPS));
System.out.println("Normal operator: "+loopWithNormalOperator(LOOPS));
}

public static long loopWithNormalOperator(long loops)
{
long startTime = System.currentTimeMillis();

for (long i = 0L; i < loops; i++)
{
if (rng.nextBoolean() || rng.nextBoolean())
{
i++;
}

if (rng.nextBoolean() && rng.nextBoolean())
{
i++;
}
}

return System.currentTimeMillis()-startTime;
}

public static long loopWithBitwiseOperator(long loops)
{
long startTime = System.currentTimeMillis();

for (long i = 0L; i < loops; i++)
{
if (rng.nextBoolean() | rng.nextBoolean())
{
i++;
}

if (rng.nextBoolean() & rng.nextBoolean())
{
i++;
}
}

return System.currentTimeMillis()-startTime;
}
}

我收到以下输出:

Bitwise operator: 2502
Normal operator: 1806

所以按位运算符实际上比“正常”运算符慢。我的第一个想法是,也许随机数生成器生成的 boolean 值在运行时会以某种方式进行不同的处理,并且与另一个 boolean 值相比,它实际上按位比较超出了需要的范围,因为它的实际保存方式是未定义的。但后来我认为这可能是由于条件运算符的“短路”机制而发生的,这可能不适用于按位运算符,因为按位运算符实际上可能需要两个值进行比较。

我的假设正确吗?为什么会出现这种情况?另一个特定于示例的行为并不代表 Java 逻辑运算符的实际行为?

一如既往,感谢您提前提供的任何帮助和说明。

编辑:

根据评论中的要求,我尝试改变通话并包括某种预热阶段,但仍然没有太大变化:

Normal operator: 1801
Bitwise operator: 2433

最佳答案

Louis Wasserman 的评论是正确的诊断。随机数生成器的调用次数强烈影响性能,因此短路很重要。我修改了程序,使用如下几种方法来计算调用次数:

private static boolean normalCountedRandom() {
normalCount++;
return rng.nextBoolean();
}

我还在每次运行中进行了多次测量,以消除任何启动效应问题。典型的输出是:

Bitwise operator: 1985
Normal operator: 1560
Bitwise operator: 1967
Normal operator: 1547
Bitwise operator: 2046
Normal operator: 1557
Bitwise operator: 2009
Normal operator: 1553
Bitwise Random calls: 800006428
Normal Random calls: 600030931

4:3 的比例符合预期。每个 if 执行一次强制调用。如果使用短路运算符,则只有一半会导致第二次调用,每个 if 预计 1.5 次调用,而没有短路时每个 if 调用 2 次。该比率与性能比率类似,假设调用占大部分时间,但不是全部时间。

JLS 中记录了短路行为。从技术上讲,当应用于 boolean 操作数时,&|Boolean Logical Operators 。 “普通”运算符是 Conditional-AndConditional-Or运算符。

通常最好避免迭代次数取决于随机结果,尽管在这种情况下,如果迭代次数足够,运行之间的差异很小。

关于java - 为什么按位运算符在比较 boolean 值时比 Java 中的 "normal"慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24224687/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com