淺談「Short-Circuit AND/OR」與「Bitwise AND/OR」的差別

Programing Language:Java Basics

RICK
Aug 15, 2021

概要

在撰寫程式時,「AND」和「 OR」都是用於邏輯判斷的運算子,但一般情況下,我們所使用的都是屬於「Short-Circuit」類,即「&&」和「||」,而非「Bitwise」類的「&」和「|」。

那麼「Bitwise」和「Short-Circuit」的差別在哪?且聽筆者娓娓道來。

正文

首先,先看官方文件中,「Operators」單元中的分類表,如下:

上圖紅色框示的部分,「&」與「&&」,「|」與「||」,皆歸為不同類型的運算子;其中,「&」和「|」屬於「Bitwise」類,而「&&」和「||」則是「Logical」類。

關於「Bitwise」和「Logical」的差異可以參考官方的教學文件:「Bitwise and Logical Operators」,如下:

事實上,「Bitwise」即「位元運算」,「&」和「|」都屬於其中的一種,而且它們不僅能用於「整數運算」,如下:

同時也能用於「邏輯運算」,如下:

然而,在多數的情況下,我們撰寫程式碼僅需要使用簡單「邏輯判斷」,因此,「Conditional-And Operator:&&」與「Conditional-Or Operator:||」就有用武之地了。

就如官方文件所述,「&&」幾乎等同於「& on boolean operands.」,如下:

但有一點要特別注意,就是「&&」具有「Short-Circuit」的機制,「&」則無。

「Short-Circuit」機制

至於「Short-Circuit」,它是一種「效率優化」的機制。

以「&&」為例,「&&」是「和」的意思,其輸出為真的條件就是該運算子兩邊的條件判斷皆為真;而「&&」判斷過程是由右至左,因此當「&&」在判斷時,只要右邊的條件式為「false」,那該運算就會被判斷為「false」直接輸出,而不會繼續判斷左邊的條件式,例子如下:

這段程式碼一經執行會成功打印「fasle」,倘若我們將其中的運算子「&&」置換成「&」,如下:

此時再執行一次程式碼,就會發現程式執行的結果改變了。

使用「&」作為判斷的程式碼會拋出「ArithmeticException」的異常;與使用「&&」時的結果不同。

雖然兩段程式都存在有造成異常的代碼:「 y / x > 0 」,但由於「&&」具有「Short-Circuit」的特性,所以當「Short-Circuit And」在判斷完第「x != 0」為「false」後,它就直接結束這個邏輯判斷並進入到下一行程式碼;也就是說,對於該段程式而言,造成異常的代碼:「 y / x > 0 」並不會被執行到,所以異常自然就不會產生。

反之,當我們使用「&」進行邏輯判斷時,按照其特性,它必須將所有的判斷條件都執行完畢,因此它不論前面的結果是否為「false」,都會執行到造成異常的代碼:「 y / x > 0 」,而當該段代碼一經執行,異常自然就會產生。

那麼關於「Short-Circuit」介紹就這邊,如果對於「Bitwise」有興趣的讀者們,可以參考「台大開放式課程:計算機概論」這門課程。

另外,上述介紹雖然是以「&」和「&&」關係為例,但「|」與「||」的關係亦是如此。

總結

綜觀上述,「Short-Circuit」就像是實作在「&&」和「||」的一種特性,那麼為什麼「Short-Circuit」不實作在「&」和「|」上呢?

關於這問題筆者曾思考過,事實上,該問題也曾在「StackOverFlow」上被討論過,請見「Why doesn’t the bitwise & operator short-circuit?」。

至於這問題的答案,筆者並沒有切確的答案,但根據「StackOverFlow」上的討論串,比較人多認同的回答是其可能與硬體上的「閘」控制有關,如下:

其實關於「Short-Circuit」,在「StackOverFlow」上還有許多相當有趣的討論串,有興趣可以自行搜尋,筆者就不一一著墨了。

--

--

RICK
RICK

Written by RICK

當遇到重開機無法解決的 BUG 時,那就試試關機吧。

Responses (1)