【Java】数值计算排雷指南
No.1 整數除法得整數
這是老生常談的話題了,也是很坑的一個點。
1 / 2 => 0為啥?因為整數除法,得到整數,相當于應得的浮點數會被截斷取整。
解決策略:先轉型:
(double)1 / 2 => 0.5No.2 運算后轉型會溢出
之前在做洛谷OJ題解的時候多次提到這個問題:
比如兩個int相乘再除以一個int,結果不會爆,但如果你使用int就會爆,甚至可能得到負數。
就算你用了long,也是先執行等號右邊的計算,計算的類型還是int,只不過相當于先進行了運算后進行了轉換。
我們要操作的話,寧可先轉型后運算也不要弄顛倒了。
No.3 負數取模得負數
3 % 2 => 1 -1 % 2 => -1 -3 % 2 => -1 (-3) % 2 => -1所以說,千萬別以為負數會按照正數的規則去取模,當然,只不過互為相反數的兩個數,取模結果也互為相反數。
補充,對負數取模會被認為是對其相反數取模。
取模的算法被模擬為Java代碼大概是這樣的(以a%b為例):
ans = a - a/b*b;No.4 奇偶數判定不靠譜
這里有個講究:奇偶數的判定,要用偶判斷,不要用奇判斷。
i % 2 == 1上面的判斷表達式就是奇判斷,根據上面講的取模的坑,我們就知道了,負數取模還是負數啊,怎么可能是正整數1呢?
所以,得到的偶數范圍包含了正偶數、零和負整數。
其實,用下面的偶判斷表達式更合理一些:
i % 2 == 0(可以用位運算替換)
No.5 運算符不能算大數
大數要用 java.math.BigInteger 或者 java.math.BigDecimal ,這兩個類都是非基本類型包裝類的引用類型,也不是String這種特殊類型,所以用于基本運算的 + 、- 、* 、/ 就不好使了,應該使用對象的成員方法。
No.6 不要濫用++
下面是之前總結過的四篇有關++的文章,可以讀讀:
- 探究自增運算符++的原理
- a++ + ++a到底是什么
- j=j++到底是什么
- C語言里++能隨便用嗎
No.7 不會取相反數
這也不會?別說,有時候很多人還真不會……
下面的代碼是一個很好的處理方案:
a = -a;No.8 不會構造BigInteger對象
BigInteger num1 = new BigInteger(1);上面的代碼對嗎?
答案是No!
BigInteger沒有整數構造器參數,但可以使用String,所以可以這么寫:
或者
int a = 1; BigInteger num1 = new BigInteger(Integer.toString(a));你以為這就完了?
BigInteger類中有三個好使的靜態屬性:ZERO、ONE、TWO(TWO早期兼不兼容我不知道,但我知道洛谷OJ的Java8交上去TWO會CE)
注意靜態導入(不好)或者自行使用,但卻是減免了自己構造0、1、2的麻煩。
No.9 不會讀大數
BigInteger num1 = new BigInteger(scanner.next()); BigDecimal num2 = new BigDecimal(scanner.nextDouble());這是比較聰明的,其實大可不必。
Scanner慢歸慢,能力很強的,自然可以直接生成BigInteger和BigDecimal:
這不就省事了?
No.10 不熟悉各個基本類型的范圍
別笑話,有時候真的讓人迷惑。
再有一說是,Java缺幾個東西:long double(真沒有)、long long(實際上在Java里是long)、無符號數……
推薦閱讀
未完待續
后續有想到新的東西會繼續補充分享的!
總結
以上是生活随笔為你收集整理的【Java】数值计算排雷指南的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【计算机网络】重要的Web结构组件总结
- 下一篇: java美元兑换,(Java实现) 美元