《Java從入門到失業》第三章:基礎語法及基本程序結構(五):基本算數運算符(1)

3.7運算符

      數學運算是計算機的基本用途之一,Java提供了很是豐富的運算符來支持。咱們根據運算的特色和性質,把運算符劃分爲幾組:基本算數運算符、自增自減運算符、關係運算符、位運算符、邏輯運算符、賦值運算符、其餘運算符。下面分別介紹。java

3.7.1基本算數運算符

       在Java中,採用+、-、*、/、%來表示加、減、乘、除、取餘(取模),這種運算小學就學過,無需多講,列表舉例以下:學習

運算spa

算式3d

結果(假設a=15,b=10)code

加法blog

a+bci

25數學

減法it

a-bio

5

乘法

a*b

150

除法

a/b

1

取餘

a%b

5

運算很是簡單,可是仍是有一些問題須要注意,下面分別用實例來講明。

3.7.1.1類型變化

  咱們看一段代碼:

 1 public static void main(String[] args) {  
 2         int a1 = 15;  
 3         double a2 = 15;  
 4         int b = 2;  
 5         int c = 0;  
 6         System.out.println("整數運算:");  
 7         System.out.println("a1 + b = " + (a1 + b));  
 8         System.out.println("a1 - b = " + (a1 - b));  
 9         System.out.println("a1 * b = " + (a1 * b));  
10         System.out.println("a1 / b = " + (a1 / b));  
11         System.out.println("a1 % b = " + (a1 % b));  
12         System.out.println("浮點數運算:");  
13         System.out.println("a2 + b = " + (a2 + b));  
14         System.out.println("a2 - b = " + (a2 - b));  
15         System.out.println("a2 * b = " + (a2 * b));  
16         System.out.println("a2 / b = " + (a2 / b));  
17         System.out.println("a2 % b = " + (a2 % b));  
18     } 
 

運行結果爲:

整數運算:  
a1 + b = 17  
a1 - b = 13  
a1 * b = 30  
a1 / b = 7  
a1 % b = 1  
浮點數運算:  
a2 + b = 17.0  
a2 - b = 13.0  
a2 * b = 30.0  
a2 / b = 7.5  
a2 % b = 1.0  
 

咱們看到,整數15/2=7,而浮點數15/7=7.5。在Java中,參與運算的2個數有浮點數時,就會自動將非浮點數變成浮點數來運算。

下面爲了節省篇幅,就再也不分別列出代碼和結果了。

3.7.1.2被0除問題

0.0 / 0 = NaN  
1.0 / 0 = Infinity  
-1.0 / 0 = -Infinity  
1 / 0 =   
Exception in thread "main" java.lang.ArithmeticException: / by zero  
    at ch03.JibenYunsuanfu.main(JibenYunsuanfu.java:16) 

咱們看到,浮點數0除以0,獲得NaN;正負浮點數除以0獲得正負無窮大;整數除以0會拋出異常。

3.7.1.3原碼反碼補碼

       咱們知道,Java的整型和浮點型都是有範圍的,若是運算結果超過範圍怎麼辦呢?咱們知道int型的最大值是214783647,假如咱們+1會獲得什麼結果呢?結果爲:

2147483647 + 1 = -2147483648

說明這個問題緣由以前,得先學習原碼、反碼、補碼的相關知識。

3.7.1.3.1原碼

  咱們現實生活當中,能夠用正負號來表示正負數,可是計算機中只有0和1,怎麼表示正負數呢?因而想出了一個辦法,對於固定字長n的二進制數,把2n個數劃分爲正負數,把最高位規定爲符號位,0表明正,1表明負,剩下的二進制數對應十進制數的絕對值。例如假設字長爲3,那麼一共表示8個數:

十進制

二進制

3

011

2

010

1

001

0

000

-0

100

-1

101

-2

110

-3

111

這種規定叫作「原碼」,即3的原碼是011,-3的原碼是111。看起來很完美吧,可是有2個問題:

  • 0的表示不惟一
  • 沒法將減法轉換爲加法

0的表示不惟一一目瞭然,爲何不能將減法轉換爲加法?咱們看個例子:

2 - 1 = 2 + (-1) = 010 + 101 = 111 = -3(正確結果爲1)

結果錯誤。那麼又爲何要把減法轉換爲加法呢?咱們學習過計算機組成,知道CPU中只有加法寄存器,由於計算機中處理加法比較簡單,若是要直接處理減法,須要增長邏輯部件,並且處理減法有借位問題很麻煩。所以在計算機中用原碼來進行運算和存儲行不通。

3.7.1.3.2反碼

       還有別的辦法嗎?人們又發明了「反碼」。反碼規定:正數的反碼和原碼一致,負數的反碼爲該數對應的絕對值的原碼按位取反。假設字長爲3,原碼反碼分別以下:

十進制

原碼

反碼

3

011

011

2

010

010

1

001

001

0

000

000

-0

100

111

-1

101

110

-2

110

101

-3

111

100

反碼解決了減法轉換爲加法的問題,可是額外須要多一個規定,就是當發生溢出時,須要對最低位加1。咱們看2個例子:

1 – 1 = 1 + (-1) = 001 + 110 = 111 =-0
2 - 1 = 2 + (-1) = 010 + 110 = 1000,溢出了,去掉溢出位後需再加1即000 + 001 = 001 = 1

咱們看到,結果都正確。可是仍是存在2個問題:

  • 0的表示不惟一
  • 減法轉加法,須要判斷溢出問題
3.7.1.3.3補碼

繼續探討,因而出現「補碼」。補碼規定正數的補碼和原碼一致,負數的補碼爲該數對應的絕對值按位取反後加1(若是溢出丟棄最高位)

十進制

原碼

反碼

補碼

3

011

011

011

2

010

010

010

1

001

001

001

0

000

000

000

-0

100

111

000

-1

101

110

111

-2

110

101

110

-3

111

100

101

咱們發現0的表示惟一了。另外用補碼計算減法也很簡單了,直接轉換便可(溢出直接丟棄最高位),咱們看2個例子:

1 – 1 = 1 + (-1) = 001 + 111 = 1000 = 000 = 0
2 - 1 = 2 + (-1) = 010 + 111 = 1001 = 001 = 1

喜歡鑽牛角尖的同窗就會問了,爲何使用補碼就能夠解決這些問題呢?有什麼道理嗎?我就知道你會問,還好我也惡補了這段知識,下面咱們來研究一下。

3.7.1.3.4補碼原理

       咱們知道,對於一個3位的二進制,對應的十進制爲0-7,一共8個。7+1=111+000=1000,去掉溢出位,又變成000即0。咱們能夠說這8個數字造成了一個閉環。這其實對應數學中的一個概念:模。

  模是指一個計量系統的計數範圍,例如咱們熟悉的時鐘,它的計數範圍是0-11,模是12。計算機也能夠當作一個計量機器,由於計算機的字長是定長的,即存儲和處理的位數是有限的,所以它也有一個計量範圍,即都存在一個「模」。對於字長3位的機器來講,計數範圍是0-7,模是8。「模」實質上是計量器產生「溢出」的量,它的值在計量器上表示不出來,計量器上只能表示出模的餘數。任何有模的計量器,都可化減法爲加法運算。

  咱們以時鐘爲例:當前時間是2點,逆時針撥2格變成0點。順時針撥10格也是0點。假設逆時針叫減,順時針叫加,那麼對於模12的系統裏,減2和加10的效果同樣。事實上,減3和加9,減4和加8效果也同樣。咱們把2和十、3和九、4和8互稱爲補數,特色就是兩者相加等於模。所以在有模的系統裏,減去一個數,能夠變成加上它的補數,便可以把減法變成加法。

回到3位數的二進制以下圖:

咱們很容易就知道模爲8,1和七、2和六、3和五、4和4他們互爲補數。列一個表:

減數

補數

1

7

2

6

3

5

4

4

5

3

6

2

7

1

可是問題來了,3位二進制系統裏,雖然減n能夠變成加n,可是因爲沒有負數,所以計算減法,須要先計算減數的補數,例如減1,須要計算1的補數8-1。怎麼辦?聰明的你必定能夠想到,補數都是成對的,咱們把成對的補數中的一半規定爲負數是否是就能夠了?例如a-1=a+(-1)=a+7,假如咱們規定7的二進制111表明-1,那麼在計算的時候就沒有減法了。同理咱們還能夠規定110表明-2,101表明-3。至於100是表明4仍是-4,均可以,通常咱們選擇表明-4。這樣一來,對於3位二進制系統,表示數的範圍就變成-4~3,而全部的減法就變成加法了。並且這樣一來咱們還驚奇的發現:

  • 全部的正數最高位都是0,負數最高位都是1
  • 全部負數的二進制都是它所對應的絕對值的二進制按位取反後+1,就是補碼

到此爲止,咱們就搞清楚了爲何在計算中要用補碼來表示負數了。

  最後,咱們回到開頭的例子:

2147483647 + 1 = -2147483648 

如今回答這個問題太easy了。在Java中,一個數字若是不加後綴,默認就是int型的。咱們知道int型佔用4個字節,則int的系統是一個模爲232的系統。而後採用補碼規則存儲,這樣最大的正數是231-1=2147483647。這個數再加1就變成231。231的補數是它本身,可是因爲231的二進制最高位是1,咱們習慣把它規定爲負數,即-231,所以就是-2147483648。

相關文章
相關標籤/搜索