計算機科學起源於數學,早期的計算機也確實多用於數學運算,以至於后來的各路編程語言,仍然保留着古老的加減乘除四則運算。這四則運算在Java語言中有專門的運算符加以表示,像加法符號“+”對應Java的“+”,減法符號“-”對應Java的“-”,乘法符號“×”對應Java的“*”,除法符號“÷”對應Java的“/”,除此之外,還有一個求余數運算,在數學上使用mod表示,而Java對應的求余運算符為“%”。四則運算加求余數運算構成了Java編程的基礎算術,數字和運算符的書寫順序與大眾寫法並無差異,下面便是這幾種基本運算的代碼例子:
int sum = 1+2; // 求兩數相加之和 System.out.println("sum="+sum); int differ = 7-3; // 求兩數相減之差 System.out.println("differ="+differ); int product = 5*6; // 求兩數相乘之積 System.out.println("product="+product); int quotient = 81/9; // 求兩數相除之商 System.out.println("quotient="+quotient); int remainder = 40%3; // 求兩數相除之余數 System.out.println("remainder="+remainder);
運行以上測試代碼,得到如下的運算日志。
sum=3 differ=4 product=30 quotient=9 remainder=1
可見上述的運算結果符合平常的加減乘除邏輯。
整數的四則運算看來是波瀾不驚,倘若有小數參與運算,計算結果還是一樣的嗎?接下來先看個除法運算,前面的除法算的是81除以9,因為剛好能除盡,所以求得的商毫無疑義是9。那末換種除不盡的情況,比如說25除以4,按日常生活中的除法,此時求得的商應該是6.25。但是Java語言另有規定,如果被除數和除數都是整型,求得的商也只能是整型數,故而25除以4得到的商變成了6,也就是省略了小數部分。要想讓這個商成為包括小數部分的數值,就必須讓被除數和除數之一變成小數,只有其中一個是小數,Java才會把整數的除法運算轉為小數的除法運算。例如25.0/4、25/4.0、25.0/4.0這幾種寫法,都將變成雙精度類型的除法,最后求得的商也變作了雙精度數6.25。下面是前述的除法運算用到的實驗代碼:
// 被除數和除數都是整數,則求得的商為去掉小數部分的整數 int quotientInt = 25/4; System.out.println("quotientInt="+quotientInt); // 被除數和除數只要有一個是浮點或雙精度數,則求得的商保留小數部分 double quotientDouble = 25.0/4; // 25/4.0的運算結果跟25.0/4是一樣的 //double quotientDouble = 25/4.0; System.out.println("quotientDouble="+quotientDouble);
運行上面的實驗代碼,打印出來的運算日志見下。
quotientInt=6 quotientDouble=6.25
然而對小數進行除法運算,有時候計算結果並不精確,譬如以下的測試代碼:
// 因為float和double類型自身為約數表示,所以除法運算得到的商也是約數,不能保證小數部分是精確的 double quotientDecimal = 8.1/3; System.out.println("quotientDecimal="+quotientDecimal); // 對浮點數和雙精度數求余數,也存在約數造成的問題,即余數的小數部分可能並不准確 double remainderDecimal = 5.1%2; System.out.println("remainderDecimal="+remainderDecimal);
這個測試代碼的運算很簡單,8.1除以3正常求得的商為2.7,至於5.1除以2的余數正常應為1.1。可是一旦運行上述的測試代碼,會發現除法結果竟然是下面這樣的:
quotientDecimal=2.6999999999999997 remainderDecimal=1.0999999999999996
以上得到的商和余數真是叫人目瞪口呆,說好的2.7和1.1怎么走樣了呢?其實這種情況在一開始便埋下伏筆了,之前介紹浮點型和雙精度型時,提到它們本身並非精准的數值,而是一個尾數乘以10的若干次方,並且浮點型的精度只有6到7位,雙精度型的精度則為15-16位,精度以外的數字純屬打醬油的。現在Java對小數進行除法運算,打醬油部分的數字也來湊熱鬧,本來能除得盡的小數,由於些許的偏差反而變得除不盡了,以至造成畫蛇添足的尷尬。這就告訴我們,要謹慎對待小數的除法和取余數運算。