说说溢算那些事~!你的计算方式溢算了吗?(转)

 

游戏快正式上线了,今天发现一个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
时间: 2024-12-23 19:59:55

说说溢算那些事~!你的计算方式溢算了吗?(转)的相关文章

简单叙述动态公式的工资系统的计算方式

动态 简单叙述动态公式的工资系统的计算方式   问题: 简单叙述 Access 动态公式的工资系统的计算方式  回答: 以下方法显示了最简单的动态公式系统如果用于实际,你还可以将公式分组,将人员分部门不同组对应不同部门的人员等等.当然,还涉及到窗体界面编程的内容,也可以通过用代码更改控件的数据源来解决.Private Sub UpdateFormula()    'tbl_pay 表用于存放工资资料,有很多类似 FLD1 FLD2 FLD3 ... 这样的货币型字段    'tbl_formul

虚拟机VMWARE中ORACLE License的计算方式

Oracle License的计算有两种方式:按照用户数和CPU个数. 其中按CPU计算方式如下: License Number = The Number of CPU Cores  *  Core Factor 其中Core Factor 可以参考官方文档 Oracle Processor Core Factor . 如果Oracle 安装在VMWARE 上,是否也是按照这个方式计算呢? 也就是说,在虚拟机VMWARE上Oracle的License计算是否也是按照分配CPU核数来计算的呢? 关

U盘容量正确的计算方式

  U盘容量正确的计算方式         因为U盘厂家是按照1G=1000M的换算单位计算的,而电脑是按照1G=1024M计算,所以市场上标称8G容量的U盘,实际容量是只有8*1000=8000M的, 而不是我们理解的8*1024=8192M .这8000M容量里用8000M除以1024M/G(电脑)=7.8125G=7.8G,再扣去一些系统文件占的空间可能就只剩7.5G了,所以你买的8G正品U盘,在电脑上显示的容量是没有8G的,一般在7.5G左右浮动. 这种情况,普遍出现在存储行业的硬盘.U

gui-求windows的滚动条长度计算方式

问题描述 求windows的滚动条长度计算方式 如题,请问windows的滚动条是如何运作的? 我只能推测出 最大滚动距离=视窗高度-滚动条长度 但滚动条的长度又是从何而来? 视窗高度/内容高度 ?? 是不是还有系数? 是否要去掉按钮高度?

国内手机资费计算方式太复杂双向收费遭诟病

畅听卡.大众卡.如意通.动感地带.神州行.新势力.全球通.世界风--在手机资费套餐变得层出不穷,令人目不暇接的同时,手机用户对电信资费的不满之声却也日渐高涨,普遍反映各种资费套餐品种繁多.计算复杂,甚至模糊的资费构成和使用条件不利于明明白白消费. 专家呼吁,计算方式过于复杂.手机上网资费不透明和双向收费仍未真正改为单向收费是目前国内手机资费的"三宗罪",而欲破除国内手机套餐过多.资费不透明的顽疾,还是要打破电信市场的垄断局面,让电信运营商们充分竞争,这样消费者才能享受到实实在在的好处.

Java---计算机贷款支付额计算(用对话框实现)

本例演示如何编写程序来计算贷款支付问题. 下面是编写程序的步骤: 1.提示用户输入年利率.年数和贷款总额 2.利用年利率算出月利率 3.通过前面的公式计算月支付额. 4.计算总支付额,它是月支付额乘以12再乘以年数. 5.在消息对话框中显示月支付额和总支付额. package cn.hncu.Chapter2; import javax.swing.JOptionPane; /** * @author hncu_chx * * Mylove amin * */ public class Comp

“百度权重”计算方式及漏洞分析

笔者于五月三号发表了一篇<站长们不要再迷恋"百度权重"了>,在站长们热议的同时,也遇到一些站长的质疑.本篇文章主要是解答关于"百度权重"的一些问题. 一."百度权重"是什么? 通过上一篇文章,大家都知道了"百度权重"并不是百度官方推出的.而是爱站网.站长工具等一些第三方网站查询站根据自身的算法而给出的一个数值,有一定的参考价值,但是不能太看重,因为有很多不足之处. 现在会有很多站长质疑:"百度权重&quo

虚拟环境下微软Windows Server许可证的计算方式(Revision 2)

08年底曾经写过一篇博文介绍这个,时过境迁,当时的文章可能有些过时了,所以在这里作一个补充和更新. 当然你可以去微软网站看个仔细: http://www.microsoft.com/licensing/about-licensing/virtualization.aspx 或者下载这个文档: http://download.microsoft.com/download/F/C/A/FCAB58A9-CCAD-4E0A-A673-88A5EE74E2CC/Licensing_Microsoft_S

U盘真实容量的计算方式

  新买的一个8G U盘,插在电脑上显示的容量只有7点几G,也只能复制7点几G的文件过去,是不是购买到的是虚标的U盘呢?其实,这个结论应该是不正确的,还是要看具体问题,下面就给您来分析一下吧: 因为U盘厂家是按照1G=1000M的换算单位计算的,而电脑是按照1G=1024M计算,所以市场上标称8G容量的U盘,实际容量是只有8*1000=8000M的, 而不是我们理解的8*1024=8192M .这8000M容量里用8000M除以1024M/G(电脑)=7.8125G=7.8G,再扣去一些系统文件