Java SE基础知识(三)--浮点数(小数)的运算符

Java SE 是什么,包括哪些内容(三)?

本文内容参考自Java8标准

一、代码运行机制相关的内容:

  • 1、 浮点数类型的运算符以及运算规则(“你能用的运算符全在这里了!”)
    • ⑴、浮点数在计算机中的表示 请参看我的博文"定点数与浮点数(小数)"
    • ⑵、浮点数的运算 主要涉及到的是浮点数运算类型之间的转换
      Java语言提供了很多作用于浮点数的运算符:
      特别提示: Java中的浮点数只有两种类型,一种是double类型(64位),一个数是float类型(32位),如果参与运算都是float类型,那么结果都是float类型,如果参与运算的都是double类型,那么结果就是double类型,如果参与运算的一个是flaot类型,一个是double类型,那么结果是什么类型?可以很肯定的说,结果是double类型,因为在这种情况下,float类型会自动转换成double类型。
      下面我们来详细了解一下与浮点数类型有关的运算符。
      这里讨论的范围都仅限两种类型(float,double)。
      还有一个问题需要强调: 如果没有特别说明,以下内容涉及到浮点数的都是float类型!
      • ①、比较运算符一共有6个(">","<",">=","<=","!=","=="),结果类型为布尔类型(这些运算符都很常见,就不一一介绍了):
         // 比较运算符左右两边的操作数都是浮点数类型,
         //结果类型为boolean,
         //表示运算结果是真还是假(true or false)
             public boolean a = 3.3>5.2//表示大于关系
             public boolean b = 5.3>=3.3//表示大于等于
             //关系
             public boolean c = 3.2<=5.1//表示小于等于
             //关系
             public boolean d = 3.2<5.1//表示小于关系
             public boolean e = 3.1==5.5//表示相等关系,
             单个"="是赋值
             public boolean f = 3.0!=5.0//表示不等关系
             //比较运算符左右两边除了可以是确切的值
             //以外,还可以是浮点数类型的变量
             //先声明两个浮点数类型的变量:
             public float a = 5fpublic float b = 6fpublic boolean i = a==b;
        
      • ②、数值运算符
        数值运算符一共有7个(’’+","-"," * “,”/","%","++","–"),结果类型为参与运算的更高位数类型、解释请参照开头的特别提示,有一些可能不常用,此处将进行一一介绍。
        “<<”,">>","<<","~","&","^","|","? :","()" 这些运算在浮点数类型里面是没有的,需要特别关注!但是在整数类型里面是有的!
        1、一元加减运算符:"+"、"-"。
        它们的功能就是简单将左右两边的数取和或者取差。
        2、一元乘法运算符:"/"," * “,”%"。
        “/”," * “–它们的功能就是简单将左右两边的数取积或者取商。
        但是”%"是取余数操作,能直接获得两数相除的余数:
        // 如果想得到105.05除以11.1的余数是多少,
        //可以像如下操作
          public int a = 105.05%11.1//a的值就是5.15。
        
        105.0除以11.1的余数是5.15!
        3、自增自减运算符:"++"、"–"。
        需要重点强调的是,它们的操作数只有一个,不像一元加减乘除运算符一样的操作数有两个,功能就是简单地将一个数的值加1,但是容易产生混淆的地方在于,它们放置的位置。即可以放置在一个数的前面,也可以放置在一个数的后面。
        // 自增自减运算符前置
            public float a = 5.1f
            public float b = ++a;
            public float c = a--//自增自减运算符后置
            public float a = 5.1fpublic float b = a++public float c = a--
        那么放在前面和后面到底有什么区别呢?
        实际上这个运算符是根据操作变量的实际需求而特别创建出来的。
        那么,变量是什么呢?你编写的每一行Java代码,在运行的时候都会对应至硬件的操作,声明一个变量(public float a = 5.1f;)实际上代表的就是在Java堆栈里新开一个内存空间(这个空间的类型是 float,换句话说就是这个空间只能存储 float类型的值,也就是32位,空间的名称是"a",空间的值是5.1f),然后把你赋给变量的值存储在空间里。通常在代码中都是声明一个变量的时候就赋值,这个操作叫做变量的初始化。然后在接下来的编码过程中可能会不断修改这个变量的值(也就是修改这个变量的内存空间所保存的值),以达到某种编程目的(功能)。
        了解了以上的内容之后,再回过来看这个自增自减运算符。它的作用其实就是能直接将变量的值直接+1或者直接-1。而前置和后置的区别就在于这个+1或者-1的时机。
        如果想使用一个变量的值,在使用完之后让这个值立即+1。那么很明显是后置(因为是先使用值再+1)。
        如果想先+1,再使用值,那么很明显是前置(因为是+1,再使用)。在一般的开发中,多半使用后置。除非是特别的功能需求,或者是编程目的,才会使用前置,如果了解了实质,那么,使用起来就会得心应手。
        还有一个问题,很多人会疑惑。比如a和a++是什么关系?a++会不会比a大1。不会,其实这个也很好理解。a和a++都是变量标识符,都指向同一块内存区域的同一个值,甚至你可以说a和a++其实是完全相同的,如果你不想让a表示的内存空间的值自增,就直接在代码中写a,如果你想让这个内存空间在这次使用完之后自增,就直接在代码中写a++。a++只是比a多一个自增的功能,其他完全一样。
        如果还理解不了,我们再从另一个角度来理解,比如,你在代码中声明了一个整数变量: float a = 5.1f;这个时候你又写了一行代码:a++;那么这个时候你知道标识符a代表的那个内存空间的值会自增1,那么自增了1之后的值是6.1f,那么这个6的标识符还是a,并没有换。所以,你继续写一行代码System.out.println(a),将a的值打印到输出台,我们都知道是6.1f。如果这个时候我们继续写一行代码System.out.println(a++);那么打印出来的值是几呢?是6.1f。因为是后置的,先使用值(a的值就是6.1f),再自增。所以总结起来就是,自增自减运算符会改变变量的值,但是不会改变变量的标识符,a和a++表示的值是相等的,只是a不会自增,a++会。
        PS:++a的情况请自己根据上面的推理得出结果。
        自增自减运算符在for和while循环中很常见。
      • ③、条件运算符(" ? : “)
        条件运算符有两个符号,第一个是”?",第二个是":"。我们先来看一个具体的例子,直接上代码更快理解:
        float a = c>b?c:b;
        这个表达式的意思是:首先,声明了一个int类型的变量,标识符为"a",然后需要给这个a 赋值。一般我们都是直接float a = 5.1f;就是直接使用字面量值(5.1f这种就是所谓的"字面量值"),但是这里使用了另外的表达方式, 直接用一个变量赋值给变量,这也是允许的,那么后续的"c>b?c:b"是什么意思呢?之所以称之为条件运算符,是因为存在条件的,这个条件是什么?条件就是"c>b"这个表达式是否成立?如果成立那么整个表达式"c>b?c:b"的结果就是":“左边的值,也就是c,如果不成立,就是b。所以完整的描述的就是:我在给int类型的变量a赋值,但是有两个选择,一个是c,一个是b,所以在赋值的时候,先比较一下大小,如果c大于b,则将变量c的值赋给变量a,否则将变量b的值赋给变量a。
        我们可以看出,条件运算符以”?“为中心,左边的是一个结果为boolean的条件表达式,右边是结果的选择,结果的选择仅限两种,用”:“分隔,如果boolean结果为true,则结果为”:",否则为":"右边。
      • ④、强制转换运算符
        强制转换运算符一般用于将内存容量大的数据类型转换为内存容量小的数据类型,比如将IEEE 754 32位表示法的double类型转换为IEEE 754 64位表示法的float类型,这种转换直接涉及到内存空间的转换。
        比如要将64位的double类型直接转换为32位的float类型就是很直接的将64位中的前32位直接抹掉, 剩下的32位二进制是多少那么转换的结果就是多少。所以说,强制转换容易丢失精度,如果一个数值已经超出了float类型的数值范围,在强制转换为float的过程中,也就是将前32位直接抹掉的过程中,会损失一部分有效的二进制表示位,转换得到的结果较转换前的值会有变化,所以强制转换操作一定要谨慎!下面展示如何用代码表示强制转换:
        // 将double类型强制转换为float类型
        //首先声明一个double类型的变量,标识符为a,
            double a = 9544534536456336454755
            64565534534545755.0//声明一个float类型变量来接受double类型,
         //这个时候如果要将a强制转换为float类型
         //则需要在标识符a前面加上强制转换符
         //(float),这样就将a强制转换为了float类型。
         //变量a将由64位存储立即变为了32位存储
           float b = (float)a;
        
        我们来看一下实际操作的结果:
        强制转换过程中,超出了float的表示范围,就是Infinity!
        从结果可以看出,954453453645633645475564565534534545755.0用32位二进制已经无法表达,超出了float类型的数值范围,在强制转换类型的过程中损失了精度,导致结果是Infinity。
        强制转换符不仅在基本类型中能使用,在后面即将提到的对象类型转换中也能使用,可以在父子类型之间相互转换。
      • ⑤、字符串连接运算符
        因为字符串属于引用类型,不属于基本数据类型,所以这里将不详细描述,在这里,只需要知道还有这么一个东西就型。在解读字符串的博文中会详细提及!
      • ⑥、对象类型判断符(“instanceof”)
        这个操作符属于引用类型,将在引用类型的章节进行详细描述,在这里只需要知道有这么一个东西就行。
  • 3、Java中有关运算的特殊情况说明(“这些情况你必须知道”):
    • ⑴、我们来看一下浮点数类型除0是什么结果:
      float类型除以0.0(注意这个0.0,在这里,需要统一类型,保证你除 的也是浮点数的0):
      在这里声明float类型的时候一定要专业,最好不要出现"float a = 5"这种情况,一定是"float a = 5.0f"
      float类型除以0结果是Infinity!
      程序居然得出了结果,没有报错,看到这里,心情是不是只能用"卧槽"来形容。再继续看一下double类型。
      double类型除以0.0:
      double类型除以0结果是Infinity!
      PS:实际上,浮点数除以整数0,结果也是Infinity,有兴趣的可以自行尝试试验一下。
      但是这里有必要提示的一点是:任何整数和浮点数进行运算,得到的结果都是浮点数!
      我们从结果中可以看出,浮点数类型除以0.0是没问题的,至少从Java语言这个角度来说是没问题的,因为得出了结果"Infinity",程序没有报错。但是,如果你想将得到的结果(Infinity)继续用于后续的运算中,那是会出问题的,因为目前我们只聚焦于除以0的讨论,Infinity不在本章的讨论范围,故在此不讨论"Infinity"的相关特性(有JavaScript编程经验的人应该对Infinity很眼熟),有兴趣的可以继续关注后续博文。
      我们再来看一下0.0除以浮点数是什么情况:
      0.0除以float类型:
      0.0除以float类型结果为浮点数类型的0.0!
      double类型的结果也是0.0。
      我们再来看一下0.0除以0.0是什么情况:
      0.0除以0.0结果是NaN!
      0.0除以整数类型的0结果是NaN,有过JavaScript编程经验的看到"NaN"也应该比较熟悉。因为本章只涉及计算结果的讨论,NaN的特性不在本章的讨论范围,有兴趣可以关注后期博文。
      以上的内容,纯粹需要靠记忆力,没有什么规律可循,Java中这些类型的计算规则,能用正常数值表示的就用正常的数值表示,不能用数值表示的,就是规定,规定的意思就是,就是这样做,没有什么理由,比如Infinity、NaN等(Infinity和NaN的意义后期博文会陆续解读)。

      PS:时间有限,有关Java SE的内容会持续更新!今天就先写这么多,如果有疑问或者有兴趣,可以加QQ:2649160693,并注明CSDN,我会就博文中有疑义的问题做出解答。同时希望博文中不正确的地方各位加以指正!

猜你喜欢

转载自blog.csdn.net/ruidianbaihuo/article/details/87637412