• float与double基本数据类型分析


    float 大小为 32-bit  

    存储的结构:1位符号位,8位指数(幂),23位尾数

    double 大小为 64-bit    

    存储的结构:1位符号位,11位指数(幂),52位尾数

    float与double结构类似,下面以float为例子做分析:

    1、通过程序的方式获取float的二进制表示:

    public class FloatTest {  
        public static void main(String[] args) {  
            float f = 8;  
            //因为int型与float型在内存中的长度相同,用floatToIntBits()可以把float中的二进制标示转为int型表示。类似double可转为long
            int i = Float.floatToIntBits(f); 
            System.out.println(Integer.toBinaryString(i)); 
        } 
    } 

    2、通过计算的方式获取float的二进制表示:

    以float f = 20014999 为例

      1)20014999 的二进制为1001100010110011110010111

      2)规格化后 1.001100010110011110010111*2^24

         尾数为001100010110011110010111

           此时24位,但float的尾数只有23位。四舍五入后为00110001011001111001100

      3)幂为24+127 二进制为:10010111。

        其中127为 float的偏移附加,double的偏移附加为1023。具体解释参照:IEEE 754 (二进制浮点数算术标准)

      4)加上符号位0。  0表示正数,1表示负数

      最后,内存中的表示为:0 10010111 00110001011001111001100

    上面的过程中可以看出float精度丢失的原因。需要高精度,如金额的计算不能用浮点型,一般可用BigDecimal。

    使用BigDecimal需要注意的一点是:BigDecimal 也有一些令人奇怪的行为。尤其在使用 equals() 方法来检测数值之间是否相等时要小心。 equals() 方法认为,两个表示同一个数但换算值不同(例如, 100.00 和 100.000 )的 BigDecimal 值是不相等的。然而, compareTo() 方法会认为这两个数是相等的,所以在从数值上比较两个 BigDecimal 值时,应该使用 compareTo() 而不是 equals() 。

     3、float、double、long型 常量的表示问题。

      float 型常量后面加F  or   f   如   3.14f

      double 型常量后面加D  or   d   或者不加    3.14d  or  3.14(默认为双精度)

      long 型常量   加L or  l 

      int 型常量     不加后缀

      一般我们都不加这个后缀,其实是因为程序做了类型转换。

      但当超出范围时需要注意。

      如:

    long L1 = 8888888888;//会报错,因为8888888888为int型常量,但超出了int的范围。

    *花边知识:

    1、计算机上表达实数有两中方法:定点表示(fixed-point)和浮点表示(floating-point)。

    2、上面的提到的方法Float.floatToIntBits()的jdk 1.7的源码如下:

        public static int floatToIntBits(float value) {
            int result = floatToRawIntBits(value);
            // Check for NaN based on values of bit fields, maximum
            // exponent and nonzero significand.
            if ( ((result & FloatConsts.EXP_BIT_MASK) ==
                  FloatConsts.EXP_BIT_MASK) &&
                 (result & FloatConsts.SIGNIF_BIT_MASK) != 0)
                result = 0x7fc00000;
            return result;
        }

    其中的 floatToRawIntBits();方法的实现为:

     public static native int floatToRawIntBits(float value);

    这里用到native因为这个方法的实现需要操作内存,所以但在java无法实现,只能通过调用C语言来实现底层的操作。

     3、前人研究:

     java float double精度为什么会丢失?浅谈java的浮点数精度问题

    http://blog.csdn.net/abing37/archive/2010/02/27/5332798.aspx

    Java中的double类型数据存储探析

    http://blog.csdn.net/softwater007/archive/2008/11/18/3330619.aspx

    IEEE754 学习总结

    http://www.pediy.com/bbshtml/BBS6/pediy6610.htm

    使用浮点数和小数中的陷阱

    http://www.360doc.com/content/07/0308/10/14474_388882.shtml

    4.相关规范

    IEEE754:http://babbage.cs.qc.edu/courses/cs341/IEEE-754references.html

    SUN 公司的 http://docs.sun.com/source/806-3568/ncg_math.html

  • 相关阅读:
    [20211108]索引分裂块清除日志增加(唯一索引)2.txt
    [20220104]in list 几种写法性能测试.txt
    [20211215]提示precompute_subquery补充.txt
    [20211217]滑稽可笑的程序代码2.txt
    SourceTree通过配置SSH来链接GitLab
    Docker在虚拟机中的安装
    .Net 6 Log4Net【.Net Core】
    es(elasticsearch)磁盘清理记录
    JSON 之 Jackson
    git FAQ
  • 原文地址:https://www.cnblogs.com/wuchangming/p/2983559.html
Copyright © 2020-2023  润新知