說說溢算那些事~!你的計算方式溢算了嗎?


游戲快正式上線了,今天發現一個bug,讓人哭笑不得。數據計算溢出了;玩家充值的元寶變為了0;這個可是一件大事,畢竟誰都擔不起這個責任啊;

來說說原因吧。開發語言是 java 工具是 netbeans ide 8.0.2

玩家對象有一個屬性是 gold 是int類型的;

玩家充值的時候計算方式如下.

        int gold = 20000;//玩家原有的
        int tempGold = 20000;//玩家現在充值的

        if (Integer.MAX_VALUE >= gold + tempGold) {
            gold = gold + tempGold;
        } else {
            gold = Integer.MAX_VALUE;
        }

看上去好像沒什么問題是吧。當然以上是模擬的;

如果你經驗豐富的話,或以下看出一些端倪,那就是會溢算的;

也許可能你看不出什么問題,我剛開始也沒發現什么問題,所以代碼就這么寫了,那好,我們來模擬一下

        int gold = Integer.MAX_VALUE - 1800;//玩家原有的
        int tempGold = 20000;//玩家現在充值的
        if (Integer.MAX_VALUE >= gold + tempGold) {
            gold = gold + tempGold;
            System.out.println("1");
        } else {
            gold = Integer.MAX_VALUE;
            System.out.println("2");
        }

 

好大家猜一猜,這是會輸出什么結果????

也許你會回答輸出 2 對。沒錯我也以為會輸出 2 ,

可是運行結果為什么是 1 呢?

首先我們分析一下,為什么我們以為會輸出 2 ?那么很明顯我們把

gold + tempGold

這兩個值的計算想當然的以為會變成 long 型 而大於 Integer.MAX_VALUE

然而事實並非這樣,我來看看輸出結果

        int gold = Integer.MAX_VALUE - 1800;//玩家原有的
        int tempGold = 20000;//玩家現在充值的
        if (Integer.MAX_VALUE >= gold + tempGold) {
            gold = gold + tempGold;
            System.out.println("1");
        } else {
            gold = Integer.MAX_VALUE;
            System.out.println("2");
        }
        System.out.println(gold + tempGold);

 

--- exec-maven-plugin:1.2.1:exec (default-cli) @ game-gamesr ---
1
-2147445449
------------------------------------------------------------------------
BUILD SUCCESS

 

在java的機制下 gold + tempGold 相加並非變成 long 型而是負數

看到這里,也許你會嘲笑我,好吧我承認,我確實沒有驗證過這個問題。好在游戲還沒有上線。測試發現問題。

不管這樣,現在我發現了這個問題,並且了解到了問題所在。好吧想辦法解決唄。

也就是把 int 轉變為 long 的問題

        int gold = Integer.MAX_VALUE - 1800;//玩家原有的
        int tempGold = 20000;//玩家現在充值的
        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);

測試一下現在的輸出結果呢?

--- exec-maven-plugin:1.2.1:exec (default-cli) @ game-gamesr ---
2
-2147463649
------------------------------------------------------------------------
BUILD SUCCESS

這些正確了,,好吧。。犯二的事情結束了。可是發現這里多了一個變量 long tempLGold;屬性和操作不是很方便,還有沒有更好的操作;

        int gold = Integer.MAX_VALUE - 1800;//玩家原有的
        int tempGold = 20000;//玩家現在充值的
        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

結果還是輸出1,也許你會嘲笑我有范二了,對我確實犯二 了,,深究才知道 運算符優先級問題。

那好吧再改改

        int gold = Integer.MAX_VALUE - 1800;//玩家原有的
        int tempGold = 20000;//玩家現在充值的
        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;//玩家現在充值的
        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

這下正確的了,,,

 

失足程序員的犯二事情啊。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM