zoukankan      html  css  js  c++  java
  • java笔记5-运算符

    运算符涉及到一些运算(这句是废话) ,需要关注精度、溢出、运算优先级、类型自动提升、强制转型等问题,会在下面的内容中逐一讲解;当然了解计算在内存中的本质才是学好的关键。

    分类:

      按照操作数的数目进行分类  单目运算符 a++  双目运算符a+b 三目运算符(a>b)?x:y  这么分类好像没有任何意义

      按照功能进行分类:

        算数运算符

          +  -  *  /  %  ++  --

          这里整数除0会抛异常,小数除0会得到Infinity

        赋值运算符

          =  +=  -=  *=  /=  %=

          单独的算数计算相对比较简单,因此把算数运算符和赋值运算符一起讲解,需要搞清楚两种运算符之间的区别

        关系运算符(比较)

          >  >=  <  <=  !=  ==  

          关系运算符比较后会返回boolean类型true false 

        逻辑运算

          &(逻辑与)  |(逻辑或)  ^(逻辑异或)  !(逻辑非)  &&(短路与)  ||(短路或)

          逻辑运算符一般用来对多个关系运算符做判断,前后连接的是boolean结果,没有计算机基础的话可能对这几个符号比较陌生,这里解释下

          &:前后都是true才返回true     |:前后有一个true就返回true    ^:前后结果不一致返回true  !:单目运算符 将boolean的值取反

          &&:当第一个条件是false时,后面的就不需要看了,如果左边的是false的时候可以提高性能     &&:当第一个条件是true时,后面的就不需要看了       

        位bit运算

          &(按位与)  |(按位或)  ^(按位异或)  ~(按位取反)  <<(按位左位移)  >>(按位右位移)  >>>(按位右位移无符号)

          讲位运算之前,需要先科普下计算机的原码、反码、补码。原码展示的是一个数的二进制数 int类型的2 就是 00000000 00000000 00000000 00000010 至于反码和补码也都是用二进制数表示,只是和原码不同的表示方式而已,在java语言中,就是以补码的形式存在的。所以我们先要搞清楚原码和补码之间的相互转换

          原码---->反码--->补码

            正数:原码、反码、补码都是一样的(-0,-128这些特殊情况后续讲解)

            负数:

              原码--->反码   符号位不变,剩余位按位取反

              反码--->补码  末位+1

              原码--->补码  符号位不变,剩余位按位取反,末位+1

          补码---->反码--->原码

            正数:原码、反码、补码都是一样的

            负数:

              补码--->反码 符号位不变,剩余位按位取反

              反码--->原码 末位+1

              补码--->原码 符号位不变,剩余位按位取反,末位+1

    System.out.println(~-4);  //3
    System.out.println(3&5);  //1
    System.out.println(-2<<1); //2147483644

          概念讲解完了,来分析下上面几行代码的实际步骤

          -4的按位取反:

            -4的原码是 10000000 00000000 00000000 00000100

            -4的反码是 11111111     11111111      11111111      11111011

            -4的补码是 11111111 11111111 11111111 11111100               ---这就是-4这个数在java中的实际展示

            -4的按位取反(取反以后还是补码的形式) 00000000 00000000 00000000 00000011

            -4按位取反后的原码  00000000 00000000 00000000 00000011         ---所以-4按位取反以后得到的结果是3

          3&5:       

            3的原码是 00000000 00000000 00000000 00000011

            3的补码是 00000000 00000000 00000000 00000011

            5的补码是 00000000 00000000 00000000 00000101  

            按位与1相当与true 0相当与false

            按位与的结果(补码) 00000000 00000000 00000000 00000001

            正数的补码还是其本身 所以3&5结果是1

          -10>>>1 

            -8的原码是 10000000 00000000 00000000 00001000

            -8的反码是 11111111 11111111 11111111 11110111

            -8的补码是 11111111 11111111 11111111 11111000

            无符号右移一位后(补码)  01111111 11111111 11111111 11111100    因为正数的补码是其本身,转化成原码得到十进制 2147483644

            

     

    精度

      整型的计算是精确的,浮点型的是不精确的,尽量不要使用浮点型去计算,这里有一个没解决的问题为什么x是0.1y是0.0999.....

    int a = 5;
    int b = 5/2;   //b=2
    double x = 1.0/10;      //0.1
    double y = 1-9.0/10;   //0.09999999999999998

    溢出

      整数由于存在范围限制,如果计算结果超出了范围,就会产生溢出,而溢出不会出错,却会得到一个奇怪的结果

      整数运算在除数为0时会报错,而浮点数运算在除数为0时,不会报错,但会返回几个特殊值

         

    int a =2147483647;
    a=a+1;     //-2147483648  
    double d1 = 0.0 / 0; // NaN
    double d2 = 1.0 / 0; // Infinity
    double d3 = -1.0 / 0; // -Infinity

    类型自动提升

      类型自动提升考虑的是不同基本类型之间的计算,提升的方法,可以参考java核心卷I:

      如果两个操作数其中有一个是double类型,另一个操作就会转换为double类型。

      否则,如果其中一个操作数是float类型,另一个将会转换为float类型。

      否则,如果其中一个操作数是long类型,另一个会转换为long类型。

      否则,两个操作数都转换为int类型。

    一些容易出错的地方

    byte x = 1;
    x=x+1 //报错
    x=(byte)(x+1);  //x是变量空间里的byte类型  1是常量区里的int类型1 相加的时候会类型自动提升到int,再次赋值给byte类型的时候需要强制类型转换
    x+=1 //这里不会报错

      同样是byte类型 x=x+1会报错,报错的原因在代码在代码注释中已经解释过了,x+=1为什么不会报错,这里有两种解释,

        一种在笔记3中提到过,也是赋值运算符的特性,如果等号右边是常量则 会自动把int类型的1变成byte类型的1

        另一种解释:复合赋值 E1 op= E2等价于简单赋值E1 = (T)((E1)op(E2))其中T是E1的数据类型,op为操作符 我个人倾向第二种解释更好理解些,当然同时引申出来的问题就是复合赋值会有精度的损失。

    关于赋值运算的运算解析 博客https://blog.csdn.net/honeygirls/article/details/81321512说的很详细,这里引用下

     

      

  • 相关阅读:
    RN-Android构建失败:Caused by: org.gradle.api.ProjectConfigurationException: A problem occurred configuring root project 'AwesomeProject'.
    Android更新包下载成功后不出现安装界面
    真机调试: The application could not be installed: INSTALL_FAILED_TEST_ONLY
    react native 屏幕尺寸转换
    Android Studio生成签名文件,自动签名,以及获取SHA1和MD5值
    React Native安卓真机调试
    git提交代码报错Permission denied, please try again
    The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.
    命令行设置快捷命令
    Linux 常用指令
  • 原文地址:https://www.cnblogs.com/ysmdbk/p/10905780.html
Copyright © 2011-2022 走看看