運算html
第一節咱們談了經過變量定義數據,上節咱們介紹了給數據賦值,有了初始值以後,能夠對數據進行運算。計算機之因此稱爲"計算"機,是由於發明它的主要目的就是運算。運算有不一樣的類型,不一樣的數據類型支持的運算也不同,本文介紹Java中基本類型數據的主要運算。程序員
算術運算swift
算術運算符有加減乘除,符號分別是+-*/,另外還有取模運算符%,以及自增(++)和自減(--)運算符。取模運算適用於整數和字符類型,其餘算術運算適用於全部數值類型和字符類型,其餘都符合常識,但字符類型看上去比較奇怪,後續文章解釋。c#
減號(-)一般用於兩個數相減, 但也能夠放在一個數前面,例如 -a, 這表示改變a的符號,原來的正數會變爲負數,原來的負數會變爲正數,這也是符合咱們常識的。數組
取模(%)就是數學中的求餘數,例如,5%3是2,10%5是0。spa
自增(++)和自減(--),是一種快捷方式,是對本身進行加一或減一操做。設計
加減乘除大部分狀況和直觀感受是同樣的,都很容易理解,但有一些須要注意的地方,而自增自減稍微複雜一些,下面咱們解釋下。code
加減乘除注意事項htm
運算時要注意結果的範圍,使用恰當的數據類型。兩個正數均可以用int表示,但相乘的結果可能就會超,超出後結果會使人困惑,例如:對象
int a = 2147483647*2; //2147483647是int能表示的最大值
a的結果是-2。爲何是-2咱們暫不解釋,要避免這種狀況,咱們的結果類型應使用long,但只改成long也是不夠的,由於運算仍是默認按照int類型進行,須要將至少一個數據表示爲long形式,即在後面加L或l,下面這樣纔會出現指望的結果:
long a = 2147483647*2L;
另外,須要注意的是,整數相除不是四捨五入,而是直接捨去小數位,例如:
double d = 10/4;
結果是2而不是2.5,若是要按小數進行運算,須要將至少一個數表示爲小數形式,或者使用強制類型轉化,即在數字前面加(double),表示將數字看作double類型,以下所示任意一種形式均可以:
double d = 10/4.0; double d = 10/(double)4;
以上一些注意事項,我想也沒什麼特別的理由,大概是方便語言設計者實現語言吧。
小數計算結果不精確
不管是使用float仍是double,進行運算時都會出現一些很是使人困惑的現象,好比:
float f = 0.1f*0.1f; System.out.println(f);
這個結果看上去,不言而喻,應該是0.01,但實際上,屏幕輸出倒是0.010000001,後面多了個1。換用double看看:
double d = 0.1*0.1; System.out.println(d);
屏幕輸出0.010000000000000002,一連串的0以後多了個2,結果也不精確。
這是怎麼回事?看上去這麼簡單的運算,計算機怎麼能計算不精確呢?但事實就是這樣,究其緣由,咱們須要理解float和double的二進制表示,後續文章進行分析。
自增(++)/自減(--)
自增/自減是對本身作加一和減一操做,但每一個都有兩種形式,一種是放在變量後,例如a++, a--,另外一種是放在變量前,例如++a, --a。
若是隻是對本身操做,這兩種形式也沒什麼差異,區別在於還有其餘操做的時候。放在變量後(a++),是先用原來的值進行其餘操做,而後再對本身作修改,而放在變量前(++a),是先對本身作修改,再用修改後的值進行其餘操做。例如,快捷運算和其等同的運算分別是:
快捷運算 | 等同運算 |
b=a++-1 | b=a-1 a=a+1 |
c = ++a-1 | a=a+1 c=a-1 |
arrA[i++]=arrB[++j] | j=j+1 arrA[i]=arrB[j] i=i+1 |
自增/自減是"快捷"操做,是讓程序員少寫代碼的,但遺憾的是,因爲比較奇怪的語法和詭異的行爲,帶給了初學者一些困惑。
比較運算
比較運算就是計算兩個值之間的關係,結果是一個布爾類型(boolean)的值。比較運算適用於全部數值類型和字符類型。數值類型容易理解,但字符怎麼比呢?後續文章解釋。
比較操做符有:大於(>),大於等於(>=),小於(<),小於等於(<=),等於(==),不等於(!=)。
大部分也都是比較直觀的,須要注意的是等於。
首先,它使用兩個等號==,而不是一個等號(=),爲何不用一個等號呢?由於一個等號(=)已經被佔了,表示賦值操做。
另外,對於數組,==判斷的是兩個數組是否是同一個數組,而不是兩個數組的元素內容是否同樣,即便兩個數組的內容是同樣的,但若是是兩個不一樣的數組,==依然會返回false,以下所示:
int[] a = new int[] {1,2,3}; int[] b = new int[] {1,2,3}; // a==b的結果是false
若是須要比較數組的內容是否同樣,須要逐個比較裏面存儲的每一個元素。
邏輯運算
邏輯運算根據數據的邏輯關係,生成一個布爾值true或者false。邏輯運算只可應用於boolean類型的數據,但比較運算的結果是布爾值,因此其餘類型數據的比較結果可進行邏輯運算。
邏輯運算符具體有:
邏輯運算的大部分都是比較直觀的,須要注意的是&和&&,以及|和||的區別。若是隻是進行邏輯運算,它們也都是相同的,區別在於同時有其餘操做的狀況下,例如:
boolean a = true; int b = 0; boolean flag = a | b++>0;
由於a爲true,因此flag也爲true,但b的結果爲1,由於|後面的式子也會進行運算,即便只看a已經知道flag的結果,仍是會進行後面的運算。而||則不一樣,若是最後一句的代碼是:
boolean flag = a || b++>0;
則b的值仍是0,由於||會"短路",即在看到||前面部分就能夠斷定結果的狀況下,忽略||後面的運算。
這個例子咱們還能夠看出,自增/自減操做帶給咱們的困擾,別的操做都乾乾脆脆,賦值就賦值,加法就加法,比較就比較,它非混在一塊兒,可能會少寫些代碼,但若是使用不當,會使理解困難不少。
運算符優先級
一個稍微複雜的運算可能會涉及多個變量,和多種運算,那哪一個先算,哪一個後算呢?程序語言規定了不一樣運算符的優先級,有的會先算,有的會後算,大部分狀況下,這個優先級與咱們的常識理解是相符的。
但在一些複雜狀況下,咱們可能會搞不明白其運算順序。但這個咱們不用太操心,可使用括號()來表達咱們想要的順序,括號裏的會先進行運算,簡單的說,不肯定順序的時候,就使用括號。
序列號 |
符號 |
名稱 |
結合性(與操做數) |
目數 |
說明 |
1 |
. |
點 |
從左到右 |
雙目 |
|
( ) |
圓括號 |
從左到右 |
|
|
|
[ ] |
方括號 |
從左到右 |
|
|
|
2 |
+ |
正號 |
從右到左 |
單目 |
|
- |
負號 |
從右到左 |
單目 |
|
|
++ |
自增 |
從右到左 |
單目 |
前綴增,後綴增 |
|
- - |
自減 |
從右到左 |
前綴減,後綴減 |
||
~ |
按位非/取補運算 |
從右到左 |
單目 |
|
|
! |
邏輯非 |
從右到左 |
單目 |
||
3 |
* |
乘 |
從左到右 |
雙目 |
|
/ |
除 |
從左到右 |
雙目 |
整數除法:取商的整數部分,小數部分去掉,不四捨五入 |
|
% |
取餘 |
從左到右 |
雙目 |
|
|
4 |
+ |
加 |
從左到右 |
雙目 |
|
- |
減 |
從左到右 |
雙目 |
|
|
5 |
<< |
左移位運算符 |
從左到右 |
雙目 |
|
>> |
帶符號右移位運算符 |
從左到右 |
雙目 |
|
|
>>> |
無符號右移 |
從左到右 |
雙目 |
|
|
6 |
< |
小於 |
從左到右 |
雙目 |
|
<= |
小於或等於 |
從左到右 |
雙目 |
|
|
> |
大於 |
從左到右 |
雙目 |
|
|
>= |
大於或等於 |
從左到右 |
雙目 |
|
|
instanceof |
肯定某對象是否屬於指定的類 |
從左到右 |
雙目 |
|
|
7 |
== |
等於 |
從左到右 |
雙目 |
|
!= |
不等於 |
從左到右 |
雙目 |
|
|
8 |
& |
按位與 |
從左到右 |
雙目 |
|
9 |
| |
按位或 |
從左到右 |
雙目 |
|
10 |
^ |
按位異或 |
從左到右 |
雙目 |
|
11 |
&& |
短路與 |
從左到右 |
雙目 |
|
12 |
|| |
短路或 |
從左到右 |
雙目 |
|
13 |
? : |
條件運算符 |
從右到左 |
三目 |
|
14 |
= |
賦值運算符 |
從右到左 |
雙目 |
|
+= |
混合賦值運算符 |
|
|||
-= |
|
||||
*= |
|
||||
/= |
|
||||
%= |
|
||||
&= |
|
||||
|= |
|
||||
^= |
|
||||
<<= |
|
||||
>>= |
|
||||
>>>= |
|
小結
本節咱們介紹了算術運算,比較運算和邏輯運算,但咱們遺留了一些問題,好比:
這是怎麼回事呢?