zoukankan      html  css  js  c++  java
  • 说说溢算那些事~!你的计算方式溢算了吗?(转)

    游戏快正式上线了,今天发现一个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

    这下正确的了,,,

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


    http://www.cnblogs.com/ty408/p/4532969.html
  • 相关阅读:
    javascript keycode大全
    在WEB环境下打印报表的crystal的解决方案
    Trim()
    C#应用结构体变量
    锚点定位
    C# 按地址传值
    [GIIS]JS 图片 Preview
    c# 模拟网站登陆
    此数据库没有有效所有者,因此无法安装数据库关系图支持对象" 解决方法
    风讯.NET与NETCMS的选择—开源.NET内容管理系统
  • 原文地址:https://www.cnblogs.com/softidea/p/4538219.html
Copyright © 2011-2022 走看看