zoukankan      html  css  js  c++  java
  • float和double有什么区别?

    float和double在游戏行业肯定是用的很多的,虽然这是个很基础的问题,但是面试时被问到还是感觉说的不是很好。
    所以还是总结一下:

    float 单精度浮点数在机内占 4 个字节,用 32 位二进制描述。

    double 双精度浮点数在机内占 8 个字节,用 64 位二进制描述。

    浮点数在机内用指数型式表示,分解为:数符,尾数,指数符,指数四部分。

    数符占 1 位二进制,表示数的正负。

    指数符占 1 位二进制,表示指数的正负。

    尾数表示浮点数有效数字,0.xxxxxxx, 但不存开头的 0 和点。

    指数存指数的有效数字。

    指数占多少位,尾数占多少位,由计算机系统决定。

    可能是数符加尾数占 24 位,指数符加指数占 8 位 -- float。

    数符加尾数占 48 位,指数符加指数占 16 位 -- double。

    知道了这四部分的占位,按二进制估计大小范围,再换算为十进制,就是你想知道的数值范围。

    对编程人员来说,double 和 float 的区别是 double 精度高,有效数字 16 位,float 精度 7 位。但 double 消耗内存是 float 的两倍,double 的运算速度比 float 慢得多,
    C 语言中数学函数名称 double 和 float 不同,不要写错,能用单精度时不要用双精度(以省内存,加快运算速度)。
    

    简单来说,Float 为单精度,内存中占 4 个字节,有效数位是 7 位(因为有正负,所以不是8位),在我的电脑且 VC++6.0 平台中默认显示是6位有效数字;double为 双精度,占 8 个字节,有效数位是 16 位,但在我的电脑且 VC++6.0 平台中默认显示同样是 6 位有效数字

    例子:在 C 和 C++ 中,如下赋值语句:

    float a=0.1; 
    

    编译器报错:warning C4305: 'initializing' : truncation from 'const double ' to 'float '

    原因: 在 C/C++ 中(也不知道是不是就在 VC++ 中这样),上述语句等号右边 0.1,我们以为它是个 float,但是编译器却把它认为是个 double(因为小数默认是 double),所以要报这个 warning,一般改成 0.1f 就没事了。

    本人通常的做法,经常使用 double,而不喜欢使用 float。

    C 语言和 C# 语言中,对于浮点类型的数据采用单精度类型 float 和双精度类型 double 来存储,float 数据占用 32bit, double 数据占用 64bit,我们在声明一个变量 float f= 2.25f 的时候,是如何分配内存的呢?如果胡乱分配,那世界岂不是乱套了么,其实不论是 float 还是 double 在存储方式上都是遵从 IEEE 的规范 的,float 遵从的是 IEEE R32.24 ,而 double 遵从的是 R64.53。

    无论是单精度还是双精度在存储中都分为三个部分:

    符号位(Sign):0 代表正,1 代表为负。
    指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储。
    尾数部分(Mantissa):尾数部分。

    特别注意:

    当你不声明的时候,默认小数都用double来表示,所以如果要用float的话,则应该在其后加上f

    例如:float a=1.3;

    则会提示不能将double转化成float 这成为窄型转化

    如果要用float来修饰的话,则应该使用float a=1.3f

    注意float是8位有效数字,第7位数字将会产生四舍五入

    所以如果一个float变量 这样定义: float a=1.32344435; 则第7位将产生四舍五入(5及5以下的都将舍去)

    1.两个在定义时的区别

    (1)float型 内存分配4个字节,占32位,范围从10-38到1038 和 -1038到-10-38

    例float x=123.456f,y=2e20f; 注意float型定义的数据末尾必须有"f"或"F",为了和double区别

    (2)double型 内存分配8个字节,范围从10-308到10308 和 -10-308到-10-308
    例:double x=1234567.98,y=8980.09d; 末尾可以有"d"也可以不写

    2、特别需要注意的是两个浮点数的算术运算

    直接使用 +,-,*,%运算符的问题

     public class Test{
            public static void main(String args[]){
            System.out.println(0.05+0.01);
            System.out.println(1.0-0.42);
            System.out.println(4.015*100);
            System.out.println(123.3/100);
            }
        }
    

    结果:

    0.060000000000000005
    0.5800000000000001
    401.49999999999994
    1.2329999999999999
    

    原因:

    首先得从计算机本身去讨论这个问题。我们知道,计算机并不能识别除了二进制数据以外的任何数据。无论我们使用何种编程语言,在何种编译环境下工作,都要先把源程序翻译成二进制的机器码后才能被计算机识别。
    以上面提到的情况为例,我们源程序里的2.4是十进制的,计算机不能直接识别,要先编译成二进制。但问题来了,2.4的二进制表示并非是精确的2.4,反而最为接近的二进制表示是2.3999999999999999。原因在于
    浮点数由两部分组成:指数和尾数,这点如果知道怎样进行浮点数的二进制与十进制转换,应该是不难理解的。如果在这个转换的过程中,浮点数参与了计算,那么转换的过程就会变得不可预知,并且变得不可逆。
    我们有理由相信,就是在这个过程中,发生了精度的丢失。而至于为什么有些浮点计算会得到准确的结果,应该也是碰巧那个计算的二进制与十进制之间能够准确转换。而当输出单个浮点型数据的时候,可以正确输出,如

    double d = 2.4;
    System.out.println(d);
    

    输出的是2.4,而不是2.3999999999999999。也就是说,不进行浮点计算的时候,在十进制里浮点数能正确显示。
    这更印证了我以上的想法,即如果浮点数参与了计算,那么浮点数二进制与十进制间的转换过程就会变得不可预知,并且变得不可逆。

    事实上,浮点数并不适合用于精确计算,而适合进行科学计算。这里有一个小知识:既然float和double型用来表示带有小数点的数,那为什么我们不称它们为“小数”或者“实数”,要叫浮点数呢?因为这些数都以科学计数法的形式存储。
    当一个数如50.534,转换成科学计数法的形式为5.053e1,它的小数点移动到了一个新的位置(即浮动了)。可见,浮点数本来就是用于科学计算的,用来进行精确计算实在太不合适了。

    参考:
    https://my.oschina.net/zd370982/blog/724265
    https://www.jb51.net/article/159043.htm

  • 相关阅读:
    ForeignKey 的第二个位置参数on_delete
    我们为什么要用springcloud?
    使用springcloud zuul构建接口网关
    分布式环境 限流解决方案
    Spring Cloud限流思路及解决方案
    SpringBoot初始教程之Redis集中式Session管理
    分布式高并发下全局ID生成策略
    分布式日志收集收集系统:Flume(转)
    深入理解Java类加载器(ClassLoader) (转)
    各类排序算法复杂度比较
  • 原文地址:https://www.cnblogs.com/KeleLLXin/p/14060841.html
Copyright © 2011-2022 走看看