`
haowenxin
  • 浏览: 4441 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
最近访客 更多访客>>
社区版块
存档分类
最新评论

让你很容易忽视的一个整数运算

阅读更多

    Java中最普遍应用的基本数据类型数据当数int类型,其再内存中占4字节,取值范围为-2147483648~2147483647,这对一般计算足够了,也正因为如此,才更容易疏忽如下情况。

现在编写一个这样的小程序:如果一个人的心脏每分钟跳动70次,他活到70岁,那么他的心脏总共跳动了多少下?似乎这个问题在简单不过了,我们可以不假思索地就写出代码来:

public class HeartbeatTimes {
      public static void main(String[] args) {
            int lifeTimes=70*60*24*365*70;
            System.out.println(lifeTimes);
      }
}
 

        运行结果是:-1719527296
    似乎情况不是我们想象的那样,一个人的心跳居然出现了负值!
    程序只有一个运算语句,问题肯定出现在这一句代码中,我们用计算器可以算出这一句运算代码的真实结果是2575440000,将其赋值给 lifeTimes,而lifeTimes是一个int类型的变量,其取值方位为-2147483648~2147483647,这已经超过了int类型 所能标示的范围,势必造成lifeTimes的溢出,所以才会造成负值的心跳次数。
修改上面的代码:

public class HeartbeatTimes {
      public static void main(String[] args) {
            long lifeTimes=70*60*24*365*70;
            System.out.println(lifeTimes);
      }
}
 

       为了防止溢出,将lifeTimes修改为long类型,这次应该没有错误了,然而,运行程序后,输出了同样的结果-1719527296。看来需要好好 分析一下这个程序了,lifeTimes已经被声明为long类型,定然不会有溢出的风险。那么错误只能在于“70*60*24*365*70”这个表达 式了。在表达式中,几个操作数都是int类型的常量,而若干个int类型的计算结果即使超出了其所能表达的数值范围,也不会自动进行向更高数据类型的转化 (如自动转化为long)。那么也就是说,其运行结果任为int类型,但其结果已经超过了int类型所能容纳的最大值,所以,溢出便产生了。
   既然知道了错误的根源,那么自然也就有了解决的方式,只要让表达式“70*60*24*365*70”的结果为long类型就可以了。在java中,如果低数据类型与高数据类型进行混合运算时,会自动将结果转化为高数据类型(byte、short与char会转换成int类型)。而要做到这一点,也只需增加一个long类型的操作数即可。自然而然,我们很快就会联想到“1L”这个数值,在此修改程序:

public class HeartbeatTimes {
      public static void main(String[] args) {
            long lifeTimes=70*60*24*365*70*1L;
            System.out.println(lifeTimes);
      }
}
 

        这次运行结果为:-1719527296
    看来运算结果的表达式还是有错,再次进行分析,整个表达式都是乘法,计算顺序是从左到右,虽然运算结果是long类型的数据,但计算次表达式时并非从开始 (计算70*60时)就知道末尾还有一long类型数据“1L”,即运行结果并非从开始就确定了整个表达式的类型为long,而是在计算过程中,如果遇到 了更高的数据类型(如在int类型的数据运算中遇到long类型的数据)才做必要的转换。因此,当遇到“1L”时,已经计算了 70*60*24*365*70的结果,而此记过依然是存在int类型的数据中,所以,尽管表达式最终计算的结果会因“1L”而转化为long类型,但此 时溢出已经发生了,“1L”并没有起到预期的效果。
    再次修改程序,将“1L”放在最前面:

public class HeartbeatTimes {
      public static void main(String[] args) {
            long lifeTimes=1L*70*60*24*365*70;
            System.out.println(lifeTimes);
      }
}
 

        这次,终于输出了我们想要的结果:2575440000
    根据刚才的思路,是从低数据类型与高数据类型进行混合运算的角度考虑,才会联想到与“1L”相乘,其实只要把第一个操作数定义为long类型即可。
    如:long lifeTimes=70L*60*24*365*70;或者long lifeTimes=(long)70*60*24*365*70;如果改成这样long lifeTimes=(long)(70*60*24*365*70);会得出正确的结果吗?嘿嘿,试试吧!有什么问题或见解,欢迎来八零客 团队博客来讨论,80客团队成员随时欢迎!

        本文转载出处:http://www.balingke.com/archives/609.html

分享到:
评论

相关推荐

    克里奇洛乘法計算機

    克里奇洛乘法計算機可能提供了一个直观的输入框让用户输入数字,以及简洁的按钮进行操作。可能还有结果显示区,清晰地显示计算结果,甚至可能包含错误检查和异常处理机制,确保在输入无效或超出预期范围时给出适当的...

    古典加密算法之置换密码和代换密码-羽灵光Fealight

    通常,这种密码会选取一个密钥K,将明文的每一个字符(假设是数字)与K相乘,然后取结果对一个大整数M取模,得到对应的密文字符。解密过程则需要进行逆运算,即除以K再对M取模。这种方法虽然提高了安全性,但由于...

    让我们都来重视数学学习中不应忽视的习惯-草稿纸.doc

    一个整洁的草稿可以帮助学生更好地展示解题过程,减少因卷面不整洁而扣分的情况。 因此,要改善学生的数学学习效果,必须重视草稿纸的使用。建议学生使用专用草稿本,保持书写清晰,按顺序进行计算和分析。教师应当...

    人教版小学四年级数学下册小数加减法教学反思.pdf

    在小学四年级数学的教学中,小数加减法是一个重要的知识点,它标志着学生从整数运算进入到了更为复杂的数字世界。这一阶段的学习不仅要求学生掌握基本的运算规则,还要求他们能够灵活应用到实际问题中去。以下是对人...

    运算放大器使用注意事项

    例如,在反馈回路并接电容,反馈信号的相位会发生改变,很容易就会发生振荡。为了降低纹波,可以把C3与R1并联,适当增大纹波的负反馈作用,抑制输出纹波。 4. 注意运放的输出摆幅 任何运放都不可能是理想运放,...

    C语言开发----c语言坑爹大冒险.rar

    在C语言中,不同类型之间的转换如果不谨慎,很容易造成数据丢失或意外的行为。例如,将一个较大的整型值赋给较小的整型变量时,高位的数据会被截断;浮点数与整数之间的转换也可能导致精度丢失。 2. **指针操作...

    javascript表达式和运算符中的一些容易忽略的点共2

    在逻辑与运算中,如果第一个操作数为假,则不会评估第二个;在逻辑或运算中,如果第一个操作数为真,则不会评估第二个。这在条件赋值和默认参数中很常见。 3. 三元运算符:`条件 ? 结果1 : 结果2`,它是最简洁的条件...

    小数乘法总结PPT学习教案.pptx

    如果不注意,很容易丢失小数点,从而导致计算结果出错。 除了小数乘法,PPT还介绍了小数除法的计算步骤。小数除法首先要在被除数前点上小数点,然后按照整数除法的规则进行计算。过程中需要注意,商的小数点不能...

    浅谈数字示波器的死区时间.pdf

    总的来说,死区时间是数字示波器设计中的一个重要考量因素,它关乎到示波器能否准确、实时地呈现信号。随着技术的进步,尽管死区时间无法完全消除,但可以通过各种方法进行优化,以满足不同领域、不同层次的测试需求...

    Java基础之计算器

    在本主题中,我们将深入探讨“Java基础之计算器”的实现,这是一个典型的编程...同时,这也是一个很好的练习,帮助理解如何将抽象概念转化为实际代码,以及如何调试和优化程序。在实际工作中,这些技能都是必不可少的。

    单片机嵌入式编程应注意的问题

    浮点运算在单片机中是一个容易被忽视但实际上很重要的问题。许多低性能单片机不支持浮点运算,因此在需要进行浮点计算时,编译器会自动调用库函数进行近似处理,这将导致运算效率低下。为了提高效率,通常会采用定点...

    C语言高手总结的新手容易犯的错误

    对于浮点数,你可以先将其转换成整数类型再进行取模运算,或者使用其他方法实现类似功能。 #### 四、“=”与“==”的区别 **问题描述**:很多语言中使用 `=` 表示等于,但在C语言中,`=` 是赋值运算符,`==` 才是...

    Java语言的26个细节

    因此,在比较浮点数时,建议使用`Math.abs()`函数和一个很小的容差值来判断两个浮点数是否足够接近,从而避免因舍入误差引起的误判。 #### 七、`equals`方法的正确实现 Java中的`equals`方法用于比较对象的逻辑...

    c_traps_and_pitfalls.zip

    8. **浮点数精度**:C语言的浮点数运算不是精确的,因此比较浮点数时需要特别注意,通常使用一个很小的误差范围来判断是否相等。 9. **函数调用约定**:不同的编译器和平台可能使用不同的函数调用约定,不兼容的...

    C#学习中的盲点

    在C#的学习过程中,往往有一些不那么显眼但至关重要的知识点容易被初学者忽视,这些便是所谓的“盲点”。为了帮助大家深入理解C#并避免这些常见误区,我们将通过两个文档——"c#中的盲点1.txt"和"c#中的盲点2.txt...

    GO入门指南_20180826.pdf

    Go语言的程序结构清晰,它将代码分为包(package),一个程序可以包含多个包,每个包具有独立的作用域。Go语言的编译过程可以生成独立的二进制文件,也可以生成可复用的共享库。Go语言对代码格式和文档生成有一套...

Global site tag (gtag.js) - Google Analytics