說說溢算那些事~!你的計算方式溢算了嗎?
說說溢算那些事~!你的計算方式溢算了嗎?
游戲快正式上線了,今天發(fā)現(xiàn)一個bug,讓人哭笑不得。數(shù)據(jù)計算溢出了;玩家充值的元寶變?yōu)榱?;這個可是一件大事,畢竟誰都擔(dān)不起這個責(zé)任?。?/p>
來說說原因吧。開發(fā)語言是 java 工具是 netbeans ide 8.0.2
玩家對象有一個屬性是 gold 是int類型的;
玩家充值的時候計算方式如下.
- int gold = 20000;//玩家原有的
- int tempGold = 20000;//玩家現(xiàn)在充值的
- if (Integer.MAX_VALUE >= gold + tempGold) {
- gold = gold + tempGold;
- } else {
- gold = Integer.MAX_VALUE;
- }
看上去好像沒什么問題是吧。當(dāng)然以上是模擬的;
如果你經(jīng)驗豐富的話,或以下看出一些端倪,那就是會溢算的;
也許可能你看不出什么問題,我剛開始也沒發(fā)現(xiàn)什么問題,所以代碼就這么寫了,那好,我們來模擬一下
復(fù)制代碼
- int gold = Integer.MAX_VALUE - 1800;//玩家原有的
- int tempGold = 20000;//玩家現(xiàn)在充值的
- if (Integer.MAX_VALUE >= gold + tempGold) {
- goldgold = gold + tempGold;
- System.out.println("1");
- } else {
- gold = Integer.MAX_VALUE;
- System.out.println("2");
- }
好大家猜一猜,這是會輸出什么結(jié)果????
也許你會回答輸出 2 對。沒錯我也以為會輸出 2 ,
可是運(yùn)行結(jié)果為什么是 1 呢?
首先我們分析一下,為什么我們以為會輸出 2 ?那么很明顯我們把
gold + tempGold
這兩個值的計算想當(dāng)然的以為會變成 long 型 而大于 Integer.MAX_VALUE
然而事實并非這樣,我來看看輸出結(jié)果
復(fù)制代碼
- nt gold = Integer.MAX_VALUE - 1800;//玩家原有的
- int tempGold = 20000;//玩家現(xiàn)在充值的
- if (Integer.MAX_VALUE >= gold + tempGold) {
- gold = gold + tempGold;
- System.out.println("1");
- } else {
- gold = Integer.MAX_VALUE;
- System.out.println("2");
- }
- --- exec-maven-plugin:1.2.1:exec (default-cli) @ game-gamesr ---
- 1
- -2147445449
- ------------------------------------------------------------------------
- BUILD SUCCESS
在java的機(jī)制下 gold + tempGold 相加并非變成 long 型而是負(fù)數(shù)
看到這里,也許你會嘲笑我,好吧我承認(rèn),我確實沒有驗證過這個問題。好在游戲還沒有上線。測試發(fā)現(xiàn)問題。
不管這樣,現(xiàn)在我發(fā)現(xiàn)了這個問題,并且了解到了問題所在。好吧想辦法解決唄。
也就是把 int 轉(zhuǎn)變?yōu)?long 的問題
- int gold = Integer.MAX_VALUE - 1800;//玩家原有的
- int tempGold = 20000;//玩家現(xiàn)在充值的
- long tempLGold = tempGold;
- if (Integer.MAX_VALUE >= gold + tempLGold) {
- gold = gold + tempGold;
- System.out.println("1");
- } else {
- gold = Integer.MAX_VALUE;
- System.out.println("2");
- }
- System.out.println(gold + tempGold);
測試一下現(xiàn)在的輸出結(jié)果呢?
- --- exec-maven-plugin:1.2.1:exec (default-cli) @ game-gamesr ---
- 2
- -2147463649
- ------------------------------------------------------------------------
- BUILD SUCCESS
這些正確了,,好吧。。犯二的事情結(jié)束了??墒前l(fā)現(xiàn)這里多了一個變量 long tempLGold;屬性和操作不是很方便,還有沒有更好的操作;
- nt gold = Integer.MAX_VALUE - 1800;//玩家原有的
- int tempGold = 20000;//玩家現(xiàn)在充值的
- if (Integer.MAX_VALUE >= gold + tempGold + 0L) {
- gold = gold + tempGold;
- System.out.println("1");
- } else {
- gold = Integer.MAX_VALUE;
- System.out.println("2");
- }
注意后面那個0L
看看輸出
- --- exec-maven-plugin:1.2.1:exec (default-cli) @ game-gamesr ---
- 1
- ------------------------------------------------------------------------
- BUILD SUCCESS
結(jié)果還是輸出1,也許你會嘲笑我有范二了,對我確實犯二 了,,深究才知道 運(yùn)算符優(yōu)先級問題。
那好吧再改改
- int gold = Integer.MAX_VALUE - 1800;//玩家原有的
- int tempGold = 20000;//玩家現(xiàn)在充值的
- if (Integer.MAX_VALUE >= 0L + gold + tempGold) {
- gold = gold + tempGold;
- System.out.println("1");
- } else {
- gold = Integer.MAX_VALUE;
- System.out.println("2");
輸出
- --- exec-maven-plugin:1.2.1:exec (default-cli) @ game-gamesr ---
- 2
- ------------------------------------------------------------------------
- BUILD SUCCESS
還可以
- int gold = Integer.MAX_VALUE - 1800;//玩家原有的
- int tempGold = 20000;//玩家現(xiàn)在充值的
- if (Integer.MAX_VALUE >= gold + tempGold * 1L) {
- gold = gold + tempGold;
- System.out.println("1");
- } else {
- gold = Integer.MAX_VALUE;
- System.out.println("2");
- nt gold = Integer.MAX_VALUE - 1800;//玩家原有的
- int tempGold = 20000;//玩家現(xiàn)在充值的
- if (Integer.MAX_VALUE >= gold + tempGold * 1L) {
- gold = gold + tempGold;
- System.out.println("1");
- } else {
- gold = Integer.MAX_VALUE;
- System.out.println("2");
- }
- --- exec-maven-plugin:1.2.1:exec (default-cli) @ game-gamesr ---
- 2
- ------------------------------------------------------------------------
- BUILD SUCCESS
這下正確的了,,,
失足程序員的犯二事情啊。。。