1. 程式人生 > >java中按位運算與邏輯運算的區別

java中按位運算與邏輯運算的區別

問題一: 

JAVA中&&和&、||和|(短路與和邏輯與、短路或和邏輯或)的區別? 


首先名稱是不同的 
&&邏輯與  ||邏輯或  它們都是邏輯運算子 
& 按位與  | 按位或  它們都是位運算子 
if(a==1&&b==2) 這是說既要滿足a=1也要滿足b=2 
if(a==1||b==2) 這是說或者滿足a=1或者要滿足b=2 
而a&b或者a|b則是二進位制的與或運算 
&同為1時為1,否則為0 
|同為0時為0,否則為1 
3&5則 
 0011 
&0101 
 0001 
等於1 

3|5則 
 0011 
|0101 
 0111 
等於7 

&&邏輯與 也叫做短路與 因為只要當前項為假,它就不往後判斷了,直接認為表示式為假 


||邏輯或 也叫做短路或 因為只要當前項為真,它也不往後判斷了,直接認為表示式為真 

問題二: 
關於Java 中邏輯運算與位運算的區別(具體到解一道題) 
題目出自Java2實用教程(第三版)(卻沒有解釋) 
程式如下圖: 
執行結果如下: 
為什麼? x,y,a,b 不是都在IF語句裡都重新賦值了嗎?按道理全為真了,y也該是20了吧?(用程式驗證過了,的確是這個結果) 


回答: 
邏輯運算子執行的是短路求值 
所謂短路,就是當參與運算的一個運算元已經足以推斷出這個表示式的值的時候,另外一個運算元(有可能是表示式)就不會執行 

比如: 
static boolean f1() { System.out.println( "function f1 called." ); return true; } 


static boolean f2() { System.out.println( "function f2 called." ); return false; } 
if ( false && f1() ) {} // f1不會被呼叫 
if ( true || f2() ){} // f2不會被呼叫 

由於&& 要求它的參與操作的兩個運算元都是布林值真,才得真,所以只要得出其中一個為假,那麼另一部分的表示式就不會被求值(在上面的例子中是f1()不會被呼叫) 
同理由於||要求它的參與操作的兩個運算元只要其中之一為真,就得真,所以只要得出其中一個為真,那麼另一部分也不會被求值(在上面的例子中是f2()不會被呼叫) 


這就是邏輯操作符所謂的“短路求值” 
位操作沒有這一特性,所以不管那邊的值是如何,任何參與運算的表示式都會被執行求值,因此也就產生了你程式碼之中的結果了。 

三、Java中邏輯運算短路的理解: 
短路” 主要用於邏輯運算子中,即 “ !   && || "這三種運算子 
短路 就是知如果左側的表示式能確定運算後的結果,則不再計算右側的表示式。 
如(1>2)&&(2<3)   明明左側已經為假 了   ,我 不用計算右側我一定知道 此表達是為假,這樣 就好似物理中的電流,當某處短路時,電流直接從一條路通過,而不再管另一條路。 

 ================================================================================

 原始碼中:   

Java程式碼  收藏程式碼
  1. // 本來可以簡單地寫成head-1,但如果head為0,減1就變為-1了,和elements.length - 1進行與操作就是為了處理這種情況,這時結果為elements.length - 1。    
  2.    elements[head = (head - 1) & (elements.length - 1)] = e;    

簡單點說:記憶體中有16位,分為高8位和低8位

255:00000000 11111111

xxx: 00110101 01010101

其作用是對低位清零,保留高位,或者是檢視是否有進位,這都是些底層的東西,你想了解更多,可以先了解組合語言。

正常程式設計時不需要這麼寫,如果你非要這麼寫,會影響你程式設計的速度,但是會極大的提高程式執行的速度。(要知道“加減乘除”最終都要被轉換為“與或非”)

  ================================================================================

JAVA位預算:

<1>.在瞭解位移之前,先了解一下正數和負數的二進位制表示形式以及關係:
舉例15和-15:

15 的原碼: 00000000 00000000 00000000 00001111 
    補碼: 11111111 11111111 11111111 11110000
                 +1 = 
-15的原碼:11111111 11111111 11111111 11110001

負數的原碼即為:正數的原碼取反,再加1。

<2>位移操作:(只針對 int型別的資料有效,java中,一個int的長度始終是32位,也就是4個位元組,它操作的都是該整數的二進位制數).也可以作用於以下型別,即 byte,short,char,long(當然,它們都是整數形式)。當為這四種類型是,JVM先把它們轉換成int型再進行操作

<<     左移   
>>     右移
>>>    無符號右移

<< 和>>為數值位移,>>>為邏輯位移。【注】:Java中不存在<<<。

$1> m<<n的含義:把整數m表示的二進位制數左移n位,高位移出n位都捨棄,低位補0.  (此時將會出現正數變成負數的形式)
例項:
  3<<2剖析:
  3二進位制形式: 00000000 00000000 00000000 00000011,按照$1的原理,得到00000000 00000000 00000000 00001100,即為12. 

  左移使整數變為負數:
  10737418<<8
  10737418二進位制表示形式:00000000 10100011 11010111 00001010,按照$1的原理,得到10100011 11010111 00001010 00000000,即為:-1546188288.

$2> m>>n的含義:把整數m表示的二進位制數右移n位,m為正數,高位全部補0;m為負數,高位全部補1.
實 例: 
  3>>2剖析:
  3二進位制形式: 00000000 00000000 00000000 00000011,按照$2的原理,得到00000000 00000000 00000000 00000000,即為0.
  -3>>2剖析:
  -3二進位制形式: 11111111 11111111 11111111 11111101,按照$2的原理,得到11111111 11111111 11111111 11111111,即為-1.

以上:每 個整數表示的二進位制都是32位的,如果右移32位和右移0位的效果是一樣的。依次類推,右移32的倍數位都一樣。

備註:對於右移32位右移0位是結果是一樣的,我一直不能夠理解。現在我只能理解為32比較特殊。相當於整體全移。移0位相同。左移也是一樣的。


$3> m>>>n:整數m表示的二進位制右移n位,不論正負數,高位都補零。
例項: 
  3>>>2剖析:
  3二進位制形式: 00000000 00000000 00000000 00000011,按照$3的原理,得到00000000 00000000 00000000 00000000,即為0.
  -3>>>2剖析:
  -3二進位制形式: 11111111 11111111 11111111 11111101,按照$3的原理,得到00111111 11111111 11111111 11111111,即為1073741823.


【注】:對於$1,$2,$3,如果n為負數:這時JVM會先讓n對32取模,變成一個絕對值小於32的負數,然後再加上32,直到 n 變成一個正數。
例項:
   4<<-10
   4的二進位制形式:00000000 00000000 00000000 00000100,-10對32取模再加上32,不用說了,得到22,則4<<-10,即相當於4<<22。
   此時按照再按照$1原理,得到00000001 00000000 00000000 00000000,得到的即為:16777216。

OK, 大功告成。

綜上所述:
   m<<n即在數字沒有溢位的前提下,對於正數和負數,左移n位都相當於m乘以2的n次方.
   m>>n即相當於m除以2的n次方,得到的為整數時,即為結果。如果結果為小數,此時會出現兩種情況:(1)如果m為正數,得到的商會無條件 的捨棄小數位;(2)如果m為負數,捨棄小數部分,然後把整數部分加+1得到位移後的值。


---------------------------------------------------------------------------------


接 下來在此說說操作的好處,速度超快,這些都是底層的二進位制機器操作指令。
  比如:a*2,

       1.jvm先為變數a分配空間;

       2.再進行a*2的操作

      3.再把結果返回給相應的變數。
而 a<<1,和a*2一樣,它只需要一條指令即可,速度很快。當然前三種位移操作都是對2的倍數

進行操作時可用。



再 進行些許補充,談到位操作,當然還要說到四個操作符:~(按位非),|(按位或),&(按位

),^(按位異或),這些都是大學 計算機基礎用法,對整數的二進位制形式進行操作,然後再

轉換為整數,具體操作如下。
1.~(按位非):【解義】對該整數的二進位制形 式逐位取反。
    ~4:(一元操作符)
     4的二進位制形式為:00000000 00000000 00000000 00000100,逐位取反後得

到:11111111 11111111 11111111 11111011,即為-5.
2.| (按位或):【解義】對兩個整數的二進位制形式逐位進行邏輯或運算,原理為:1|0=1,0|0=0,1|1=1,0|1=1
等。
    4|-5:
     4的二進位制形式為:00000000 00000000 00000000 00000100,
    -5的二進位制形式為:11111111 11111111 11111111 11111011,
  逐位進行邏輯或運算:11111111 11111111 11111111 11111111,即得到-1.
3.&(按位):【解義】對兩個整數的二進位制形式逐位進行邏輯 運算,原理:1|0=0,0|0=0,1&1=1;0&1=0等。  
   4&-5:
     4的二進位制形式為:00000000 00000000 00000000 00000100,
    -5的二進位制形式為:11111111 11111111 11111111 11111011,
  逐位進行邏輯運算:00000000 00000000 00000000 00000000,即得到0.  

實際應用:可以把位元組轉換為整 數,-64&0xFF=192,也可以用八進位制的形式,-64&0377=192、

其實0xFF和0377都表示的是整數255、 
4.^(按 位異或):【解義】對兩個整數的二進位制形式逐位進行邏輯異或運算,原理:1^1=0,1^0=1,0^1=1,0^0=0.
   4^-5:
     4的二進位制形式為:00000000 00000000 00000000 00000100,
    -5的二進位制形式為:11111111 11111111 11111111 11111011,
逐位進行邏輯異或運算:11111111 11111111 11111111 11111111,即得到-1.

實際應用:按位異或可以比較兩個數字是否相等,它利用 1^1=0,0^0=0的原理。  20^20==0

宣告:本文轉自http://uule.iteye.com/blog/2095860

相關推薦

Java運算子邏輯運算子的區別(&和&&,|和||)

位運算子 & 在運算中,計算機先判斷 & 兩邊的真假,然後才判斷整體的真假, 邏輯運算子 && 在運算中,如果計算機判斷出有一個為假時,就停止判斷, >

java運算邏輯運算區別

問題一: JAVA中&&和&、||和|(短路與和邏輯與、短路或和邏輯或)的區別? 首先名稱是不同的 &&邏輯與  ||邏輯或  它們都是邏輯運算子 & 按位與  | 按位或  它們都是位運算子 if(a==1&&b==2) 這是說既要滿足a=1也要滿足

深入理解Java的字段屬性的區別

ring rgs name 私有變量 pub tail 博文 們的 方式 轉載出處 http://blog.csdn.net/chenchunlin526/article/details/69939337 1、Java中的屬性和字段有什麽區別? 答:Java中的屬性(p

從結構上分析Java的 if/elseswitch的區別

聽同事說了一句能用if/else就別用switch,感覺這就話不對,但是又提不出什麼依據進行判斷,不能明白其中是不是有什麼深層次的原因,今天就探究一下這方面的原因。我們要明白我們的程式到底是誰幫助我們做的? 我們首先得明白計算機的五大組成部分控制器,運算器,儲存器,輸入,輸

javaBigDecimal的equalscompareTo的區別

這兩天在處理支付金額校驗的時候出現了點問題,有個金額比較我用了BigDecimal的equals方法來比較兩個金額是否相等,結果導致金額比較出現錯誤(比如3.0與3.00的比較等)。 【注:以下所講都是以sun jdk 1.4.2版本為例,其他版本實現未必一致,請忽略】

java方法的過載重寫的區別

    (1) 父類與子類之間的多型性,對父類的函式進行重新定義。如果在子類中定義某方法與其父類有相同的名稱和引數,我們說該方法被重寫 (Overriding)。在Java中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。 (adsbygoogle = window.ads

Javaa=a+b a+=b區別

就單純的執行這兩條語句,不考慮編譯器的優化的話,a=a+b的執行效率是低於a+=b的,因為它多進行了一步中間變數的操作,而且會多佔用一個變數的空間。而Java編譯器預設對其進行了優化,優化之後兩條語句都當做 a+=b來執行了,所以實際上是沒有任何卻別的。 其次說一下有關型

Javaa=a+b a+=b區別 以及和型別轉換的關係

很久之前學習過 a=a+b 和a+=b的一些區別,進來再次回想起來,發現理解的還不透徹,所以又查資料找檔案重新學習了一番。 比較這兩種運算子的區別,可以有以下兩個方面的比較: 執行效率和型別轉換。 首先說一下執行效率問題 就單純的執行這兩條語句,不考慮編譯器的優化的話,a

javalist的addaddall方法區別

在做專案時我遇到過這樣的問題,java.lang.ClassCastException: java.util.ArrayList cannot be cast to com.alibaba.getter.jstorm.biz.domain.Page。知道是型別轉換錯誤,但

java值傳遞和引用傳遞區別

java中在引數傳遞時有2種方式,         一種是按值傳遞:值傳遞是指在呼叫函式時將實際引數複製一份傳遞到函式中,這樣在函式中如果對引數進行修改,將不會影響到實際引數。簡單來說就是直接複製了一份資料過去,因為是直接複製,所以這種方式在傳遞時如果資料量非常大的話,執行

Java 運算(移位、、或、異或、非)邏輯運算

高效率 邏輯與 才會 system 區別 span get 右移 邏輯 java 位運算包括:左移( << )、右移( >> ) 、無符號右移( >>> ) 、位與( & ) 、位或( | )、位非( ~ )、位異或( ^

運算(&amp;、|、^)邏輯運算(&amp;&amp;、 ||)差別

邏輯與 清空 作用 一個數 總結 與運算 位或 定位 按位與 剛無意在一篇文章中看到了位運算(&、|)和邏輯運算(&&、||)的介紹。想起了自己薄弱的基礎知識。於是百度了幾把總結了下。 首先從概念上區分下,位

Java運算

post 得出 進制數 運算 運算符 ring 位運算 邏輯 異或 (轉載聲明:   出處:http://blog.csdn.net/vebasan/article/details/6193916   作者:vebasan  ) 位運算符主要針對二進制,它包括了:“與”、

Java運算符使用總結(重點:自增自減、運算邏輯運算

運算 計算器 可讀性 過多 移位運算 style avi 學會 new Java運算符共包括這幾種:算術運算符、比較運算符、位運算符、邏輯運算符、賦值運算符和其他運算符。(該圖來自網絡) 簡單的運算符,就不過多介紹使用了,可自行測試。關於賦值運算,可以結合算術運

java運算總結

轉自:https://www.cnblogs.com/liaopeng/p/8436155.html 1.^(亦或運算) ,針對二進位制,相同的為0,不同的為1 public static void main(String[] args) { System.out.println

java運算

由於位運算是二進位制運算,不要與一些八進位制數搞混,java中二進位制數沒有具體的表示方法。 public class BitMath{     public static void main(String[] args){         System.out.println

c++取反運算,型別轉換,擴

#include <stdio.h> #include <iostream> using namespace std; void main() {   //做這類題目抓住兩點:第一、無論是以進製表示還是整數形式賦值給變數,都要根據變數相應  //的資

附錄B小結:二進位制、十六進制、邏輯運算算術運算

1、所有的小數系統都使用了某一個數值為基礎的冪值 2、記住前15個數值的二進位制與十六進位制表現形式有助於完成它們之間的轉換工作 3、在使用無符號數值時,進位標誌有助於判斷是否發生溢位 4、使用邏輯運算子“or”,“and”,和“xor”分別來實現對位元位的設定、測試和

c++運算邏輯運算(&&和||:邏輯運算子;&和|:運算子)

兩者計算結果相同(針對各自的運算物件),只是效能上有差別而已。 &&和||:邏輯運算子 &和|:按位運算子 &&是且的意思,a&&b 兩者都為真才為真. ||是或的意思,a||b 兩者有一為真即真. &,|是位運算子.即對位進行運算,

字段有空的時候 進行邏輯運算,mysql oracle 處理函數IFNULL() nvl() ,選取NULL 值 。

ast mysql ESS not where mys 進行 add person mySQL數據庫: SELECT id_p,IFNULL(math,0)+IFNULL(english,0) 總分 from mytest_brian1 Oracle 數據庫: se