首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么按位运算符在比较布尔值时比Java中的“正常”运算符要慢?

为什么按位运算符在比较布尔值时比Java中的“正常”运算符要慢?
EN

Stack Overflow用户
提问于 2014-06-14 21:55:08
回答 1查看 853关注 0票数 0

假设如下:您有两个函数,两个函数基本上都是相同的,这就是比较两个随机布尔函数和AND和OR操作符。但是,一个函数是用普通的条件运算符&和\来完成这个任务的,另一个函数使用的是位操作符&和\。

我认为这两个函数当然需要相同的时间来完成,,但--它们不需要。与“正常”条件运算符相比,按位进行比较所需的时间多出五分之一。

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

代码语言:javascript
复制
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

对于按位运算符:

代码语言:javascript
复制
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.

嗯,这些定义并没有让我感到满意,我的问题仍然没有得到回答。因此,我做了更多的研究,并在这里发现了一个关于堆栈溢出的问题,关于位运算符对booleans的影响(Java中位运算符对布尔值的影响),但这也没有真正回答我的问题。

下面是我测试过的代码,它使用一个随机数生成器来获取随机的布尔值,以便相互比较,并在这段时间内循环。

代码语言:javascript
复制
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;
    }
}

我收到了以下输出:

代码语言:javascript
复制
Bitwise operator: 2502
Normal operator: 1806

因此,位运算符实际上比“正常”运算符慢。我的第一个想法是,也许随机数生成器生成的布尔值在运行时被处理得不一样,与另一个布尔值相比,它实际上比需要的要多,因为它是如何实际保存的。但后来我想,这可能是因为条件运算符的“短路”机制,它可能不适用于位运算符,它可能实际上需要两个值来进行比较。

我的假设正确吗?这一切为什么要发生?另一个例子--不代表Java逻辑运算符实际行为的特定行为?

一如既往,感谢您的帮助和澄清。

编辑:

按照评论中的要求,我尝试切换调用,并包含某种热身阶段,但仍然没有什么变化:

代码语言:javascript
复制
Normal operator: 1801
Bitwise operator: 2433
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-15 00:01:07

路易斯·沃瑟曼的评论是正确的诊断。对随机数发生器的调用次数对性能影响很大,因此短路是很重要的.我使用以下几种方法对程序进行了修改,以计算调用数:

代码语言:javascript
复制
private static boolean normalCountedRandom() {
  normalCount++;
  return rng.nextBoolean();
}

我还在每次运行中做了多次测量,以消除任何启动效果问题。一个典型的产出是:

代码语言:javascript
复制
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中.从技术上讲,当应用于布尔操作数时,&|布尔逻辑运算符。“正常”运算符是有条件-和有条件-或运算符。

通常情况下,最好避免迭代次数依赖于Random结果,尽管在这种情况下,迭代足够多,运行之间的差异很小。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24224687

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档