程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 計算機程序的思維邏輯 (3),思維邏輯

計算機程序的思維邏輯 (3),思維邏輯

編輯:JAVA綜合教程

計算機程序的思維邏輯 (3),思維邏輯


運算

第一節我們談了通過變量定義數據,上節我們介紹了給數據賦值,有了初始值之後,可以對數據進行運算。計算機之所以稱為"計算"機,是因為發明它的主要目的就是運算。運算有不同的類型,不同的數據類型支持的運算也不一樣,本文介紹Java中基本類型數據的主要運算。

  • 算術運算:主要是日常的加減乘除
  • 比較運算:主要是日常的大小比較
  • 邏輯運算:針對布爾值進行運算

算術運算

算術運算符有加減乘除,符號分別是+-*/,另外還有取模運算符%,以及自增(++)和自減(–)運算符。取模運算適用於整數和字符類型,其他算術運算適用於所有數值類型和字符類型,其他都符合常識,但字符類型看上去比較奇怪,後續文章解釋。

減號(-)通常用於兩個數相減, 但也可以放在一個數前面,例如 -a, 這表示改變a的符號,原來的正數會變為負數,原來的負數會變為正數,這也是符合我們常識的。

取模(%)就是數學中的求余數,例如,5%3是2,10%5是0。

自增(++)和自減(--),是一種快捷方式,是對自己進行加一或減一操作。

加減乘除大部分情況和直觀感覺是一樣的,都很容易理解,但有一些需要注意的地方,而自增自減稍微復雜一些,下面我們解釋下。

加減乘除注意事項

運算時要注意結果的范圍,使用恰當的數據類型。兩個正數都可以用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類型的數據,但比較運算的結果是布爾值,所以其他類型數據的比較結果可進行邏輯運算。

邏輯運算符具體有:

  • 與(&):兩個都為true才是true,只要有一個是false就是false
  • 或(|):只要有一個為true就是true,都是false才是false
  • 非(!):針對一個變量,true會變成false, false會變成true
  • 異或(^):兩個相同為false, 兩個不相同為true
  • 短路與(&&): 和&類似,不同之處馬上解釋
  • 短路或 (||):與|類似,不同之處馬上解釋

邏輯運算的大部分都是比較直觀的,需要注意的是&和&&,以及|和||的區別。如果只是進行邏輯運算,它們也都是相同的,區別在於同時有其他操作的情況下,例如:

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,因為||會"短路",即在看到||前面部分就可以判定結果的情況下,忽略||後面的運算。

這個例子我們還可以看出,自增/自減操作帶給我們的困擾,別的操作都干干脆脆,賦值就賦值,加法就加法,比較就比較,它非混在一起,可能會少寫些代碼,但如果使用不當,會使理解困難很多。

運算符優先級

一個稍微復雜的運算可能會涉及多個變量,和多種運算,那哪個先算,哪個後算呢?程序語言規定了不同運算符的優先級,有的會先算,有的會後算,大部分情況下,這個優先級與我們的常識理解是相符的。

但在一些復雜情況下,我們可能會搞不明白其運算順序。但這個我們不用太操心,可以使用括號()來表達我們想要的順序,括號裡的會先進行運算,簡單的說,不確定順序的時候,就使用括號。

小結

本節我們介紹了算術運算,比較運算和邏輯運算,但我們遺留了一些問題,比如:

  • 正整數相乘的結果居然出現了負數
  • 非常基本的小數運算結果居然不精確
  • 字符類型怎麼也可以進行算術運算和比較 

這是怎麼回事呢?

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

未完待續,查看最新文章,敬請關注微信公眾號“老馬說編程”,深入淺出,探索Java編程及計算機技術的本質。原創文章,保留所有版權。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved