精华内容
下载资源
问答
  • 单精度和双精度运算问题 问题引出: 当我们在运行System.out.println(1.0-0.66); 结果会是什么呢? 问题解决: 可能许多小伙伴会觉得输出0.34吧,但是事实果真如此吗? 首先,大家都知道,小数类型的数据默认是...

    学习目标:
    单精度和双精度的运算问题


    问题引出:

    当我们在运行如下输出语句时

    System.out.println(2.5-0.9);
    System.out.println(2.4-0.8);
    
    System.out.println(2.5f-0.9f);
    System.out.println((2.4f-0.8f));
    

    输出结果如下:可能很多人就会疑惑了,不都是输出1.6吗?怎么就输出各不一样呢?


    1.6
    1.5999999999999999
    1.6
    1.6000001
    

    问题解决:

    首先,大家都知道,小数默认是Double类型,也就是说1.0是双精度型。而计算机底层是以二进制的补码形式存储数据,包括在进行四则运算,取余等操作。而我们发现2.5的小数部分0.5是可以被二除尽的,即2^-1次方,此时就是问题所在,而0.9在利用短除法求二进制时,是得不到整数,也就是无法用二进制表示,但是计算机底层会将它取出前52位(化成十进制则有14位)而后面的被舍弃。此时就会出现精度损失。 float类型也是一样的,只取前7位小数。所以也会有精度损失。

    总结:在计算中只要有一个不精度损失,则结果也不损失。


    如何解决

    那如何解决两个都精度损失的数字的运算呢?就比如2.4-0.8,我还是要得到1.6,那该怎么办呢?
    这里我们推荐大家使用BigDecimal类。

    //add方法 +
    //subtract方法 -
    //multiply方法 *
    //divide方法 /
    BigDecimal d1 = BigDecimal.valueOf(2.4);
    BigDecimal d2 = BigDecimal.valueOf(0.8);
    double result = d1.subtract(d2).doubleValue();
    System.out.println(result);
    //输出结果:1.6
    

    这样问题就轻松解决了。

    展开全文
  • 计算机中float, double类型数据分别占据4,8个字节,其中float类型double可以表示的小数位数不同,导致了精度不同。double的精度更高。 计算机中数据的表示由:符号位, 指数位,尾数位组成。比如一个float类型...

    计算机中float, double类型数据分别占据4,8个字节,其中float类型和double可以表示的小数位数不同,导致了精度不同。double的精度更高。

    计算机中数据的表示由:符号位, 指数位,尾数位组成。比如一个float类型数字的二进制由左到右依次是符号位,指数位,尾数位。

    类型符号位指数位尾数位总位数(bit)
    float182332
    double1115264

    数字1.4在计算机中的存储转换如下:

    先将整数和小数都变二进制表示:1.0110 0110 0110 0110 0110 011,然后整数部分不需要右移,所以float的指数位=2*7-1+0=127;double的指数位=2*10-1+0=1023。各个部分的二进制表示如下。

     

    1.4的不同存储符号位指数位尾数位16进制表示
    float0011111110110 0110 0110 0110 0110 0113FB33333
    double0011111111110110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 01103FF6666666666666


     

    在c++单精度和双精度的运算结合如下两个test示例理解如下:

    #include <iostream>
    
    float f1 =1.4;
    float f2 = 5.0;
    float f3 = 7.0;
    int i = 7;
    using namespace std;
    
    void test1()
    {
    	printf("test %f %f %f\n", f1 * f2, f1 * 5.0, f3 / f1);
        cout << (f1 * f2 == i) << '\t' << (f1 * f2 == f3) << endl;
        cout << (f1 * 5.0f == f3) << '\t' << (f1 * f2 == f1 * 5.0f) << endl;
        cout << (f3 / f1 == 5.0) << '\t' << (f3 / f1 == f2);
    }
    
    void test2()
    {
    	printf("test %f %f %f\n", f1 * f2, f1 * 5.0, f3 / f1);
        cout << (f1 * f2 == i) << '\t' << (f1 * f2 == f3) << endl;
        cout << (f1 * 5.0 == f3) << '\t' << (f1 * f2 == f1 * 5.0) << endl;
        cout << (f3 / f1 == 5.0) << '\t' << (f3 / f1 == f2);
    }
    int main(void)
    {
    	cout<<"test1"<<endl;
    	test1();
    	cout<<endl<<"test2"<<endl;
    	test2();
    	
    	cout<<endl<<endl<<"验证输出"<<endl;
    	double f11=1.4;
    	cout<<"sizeof(5.0)="<<sizeof(5.0)<<", sizeof(f1*f2)=" <<sizeof(f1*f2)<<", sizeof(f3/f1)=" <<sizeof(f3/f1)<<endl;
    	cout.precision(20);
    	cout<<"1.4的单精度 f1="<<f1<<endl<<"1.4的双精度 f11="<<f11<<endl;
    	cout<<"双精度转单精度 double2float: "<<float(f11)<<endl;
    	cout<<"单精度转双精度 float2double: "<<double(f1)<<endl;
    
        cout<<"单精度*单精度 f1*5.0f="<<f1*5.0f<<", 单精度*双精度 f1*5.0="<<f1*5.0<<", 双精度*双精度 f11*5.0="<<f11*5.0<<endl;
        cout<<"当单精度*单精度结果有小数时候:"<<endl; 
        cout<<"单精度*单精度 f1*6.0f="<<f1*6.0f<<", 单精度*双精度 f1*6.0="<<f1*6.0<<", 双精度*双精度 f11*6.0="<<f11*6.0<<endl;
        
        cout<<endl<<"i.和j. 的验证:"<<endl;
        cout<<"f3/f2==1.4 =>"<< (f3/f2==1.4)<<",  f3/f2==f1 =>"<<(f3/f2==f1)<<endl;
        
        cout<<endl<<"d.的假设验证:"<<endl;
        cout<<"float(f1*5.0)==i =>"<<(float(f1*5.0)==i)<<endl;
        f1=0.125;
        cout<<"f1 * 56.0 == i =>"<< (f1 * 56.0 == i)<<endl;
    	return 0;
    
    
    }

    test1和test2的两段代码涉及的是float类型和double类型数据在计算机中的存储问题。

    用到的基础知识:

    1, C++中默认5.0是一个double类型,5.0f表示指定这是一个float类型的数字。

    2, 精度(float*double)=> double*double=精度(double), 精度(float*float)=精度(float), 精度(double*double)=精度(double)

    3,  float类型用4个字节表示,double类型用8个字节表示,double可以用更多的位表示小数点部分(这部分知识可以参考数字在计算机中的表示,https://blog.csdn.net/ultrakang/article/details/39322275),所以有小数的情况下,double比float精度更高。而float转double精度不变,double转float精度降低。

    4,float和double转换中精度降低的情况只作用在存在小数位情况。且只存在于小数位的非0尾数大于23bit情况下(因为float尾数是23个bit, double尾数是52个bit)。

     

    再来看本例中给定的数据 f1=1.4; f2=5.0; f3=7.0; i=7。共进行了如下的运算结果比对,跟着对应的结果分析。

    a.  f1 * f2 == i       =》1,左边 f1*f2 等效于 float*float,结果仍然是float,恰好是整数,所以f1 * f2 == i 成立。

    b.  f1 * f2 == f3     =》1,左边 同 a. ,右边f3是float类型,不涉及数据类型转换,精度不变,所以f1 * f2 == f3 成立。

    c.  f1 * 5.0f == i    =》1,左边 f1*5.0f 等效于float*float,其它同a. ,所以f1 * 5.0f == i  成立 。

    d.  f1 * 5.0 == i    =》0,左边 f1*5.0等效于double*double, f1=1.4,1.4作为float和double两种类型在计算机存储的精度是不同的,并且结果也是double类型,精度更高,所以f1 * 5.0 == i 不成立,如果将f1*5.0转换成float类型则成立,即:float(f1*5.0)==i 成立。或者将本例中f1=1.4换成f1=0.125(即一个小数点位数可在23bit之内表示的数 , 则f1 * 56.0 == i 成立,因为0.125值的float和double类型在计算机存储中是一样的。

    e.  f1 * f2 == f1 * 5.0f   =》1,右边f1 * 5.0f是float*float,不涉及类型转换问题,同b. 所以f1 * f2 == f1 * 5.0f 成立。

    f.   f1 * f2 == f1 * 5.0   =》0,右边同d. 1.4在计算机中作为float和double表示的精度不同,f1*5.0是double*double=double,比f1*f2的float*float=float精度更高,所以f1 * f2 == f1 * 5.0不成立。

    g.  f3 / f1 == 5.0     =》1,  左边float/foat=float,结果用float类型表示,小数位尾数为0,右边double类型的5.0的小数位尾数也都是0,所以f3 / f1 == 5.0 成立。可以结合下面的 i. 来理解。

    h.  f3 / f1 == f2      =》1, 左边和右边都是float类型,精度不变,所以 f3 / f1 == f2成立。可以结合下面的j. 来理解。

    补充:

    i.  f3 / f2 == 1.4   =》0, 左边结果float类型,右边1.4是double类型,精度不同,所以f3 / f2 == 1.4不成立。

    j. f3 / f2 == f1   =》1,右边类型是float,1.4用float表示,不涉及精度降低问题,所以f3 / f2 == f1 成立。

    cout默认打印出7位有效数字,所以第一行打印的结果都一样。

    上面的验证结果如图:

    展开全文
  • 分别进行100万次双精度单精度浮点数加运算,计算各消耗多少时间,打印输出累加结果。 测试代码 void fpSpeedTest(void) { int begin_tick, end_tick; double dp1 = 1.0; double dp2 = 1.0; double dp = 0.0; ...

    测试平台

    MCU: STM32F767,启动硬件双精度浮点运算协处理器
    IDE: Keil RVMDK V5.21.1.0
    浮点协处理器:启用双精度浮点协处理器
    主频:108MHz

    测试方法

    分别进行100万次双精度与单精度浮点数加运算,计算各消耗多少时间,打印输出结果。

    测试代码

    void fpSpeedTest(void)
    {
    	int begin_tick, end_tick;
    	double dp1 = 1.0;
    	double dp2 = 1.0;
    	double dp = 0.0;
    	begin_tick = HAL_GetTick();
    	for(int i = 0; i < 1000000; i++)
    	{
    		dp = dp1 + dp2;
    	}
    	end_tick = HAL_GetTick();
    	printf("double precision add 1000000 times used %d ms.\r\n", end_tick - begin_tick);
    	float fp1 = 1.0f;
    	float fp2 = 1.0f;
    	float fp = 0.0f;
    	begin_tick = HAL_GetTick();
    	for(int i = 0; i < 1000000; i++)
    	{
    		fp = fp1 + fp2;
    	}
    	end_tick = HAL_GetTick();
    	printf("single precision add 1000000 times used %d ms.\r\n", end_tick - begin_tick);
    }
    

    测试结果

    double precision add 1000000 times used 112 ms.
    single precision add 1000000 times used 197 ms.
    

    结论

    在开启 双精度浮点协处理器 的情况下,进行双精度浮点运算比单精度浮点运算消耗的时间更少,效率更高。不能仅凭直觉就认为单精度浮点运算精度低,运算速度当然更快。

    展开全文
  • java单精度和双精度的区别

    千次阅读 2021-03-17 12:15:53
    计算机处理数据都涉及到数据的转换各种复杂运算,比如,不同单位换算,不同进制(如二进制十进制)换算等,很多除法运算不能除尽,比如10÷3=3.3333.。。。。。。无穷无尽,而精度是有限的,3.3333333x3并不等于10,...

    为什么会有精度问题?

    计算机处理数据都涉及到数据的转换和各种复杂运算,比如,不同单位换算,不同进制(如二进制十进制)换算等,很多除法运算不能除尽,比如10÷3=3.3333.。。。。。。无穷无尽,而精度是有限的,3.3333333x3并不等于10,经过复杂的处理后得到的十进制数据并不精确,精度越高越精确。float有8位有效数字,double有16位有效数据,float和double都是到大到一定的值自动开始使用科学计数法,并保留相关精度的有效数字,所以结果是个近似数。如果更精确的运算小数(比如金融,数学),希望结果更符合预期值应该使用Bigcimal。计算器应该也会有精度问题,也会有二进制十进制转换。

    java的双精度和单精度的区别

    现实问题中不但有整型数值,还有小数。Java语言也提供了针对小数的存储类型,分别是float类型和double类型。

    Java语言的浮点类型有两种不同的表示形式:十进制数和科学计数法。十进制数形式,由数字和小数点组成,且必须有小数点,如0.123、12.85、26.98等;科学计数法形式,如:2.1E5、3.7e-2等。其中e或E之前必须有数字,且e或E后面的指数必须为整数。

    科学计数法

    一种简化计数的方法,对于位数较小的数值,科学计数法没有什么优势,但对于位数较多的数值其计数方法的优势就非常明显了。例如:光的速速是300,000,000米/秒,全世界人口数大约是6,100,000,000。类似光的速度和世界人口数这样大数值的数,读、写都很不方便,仔细观察上面的两个数值,光的速度可以写成3*108,全世界人口数可以写成6.1*109。这种计数方法就是科学计数法,用Java语言科学计数法表示光速是3E8,世界人口数大约是6.1E9。

    一个较大的数值(》0)可以用下面的方式来表示:

    a * 10n (1《=a《10,n为整数)

    其中,a是该数值的有效位数,有效位数从左边第一个不是0的数起,到末尾数字为止,所有的数字(包括0,科学计数法不计10的n次方),称为有效数字。例如:光速是3E8,其有效数字是1位,值是3;世界人口数大约是6.1E9,其有效数字是2位,值是6.1。

    n是该数值的整数部分减1的正整数。

    一个较小的数值(《0)可以用下面的方式来表示:

    a * 10-n (1《=a《10,n为整数)

    a的取值同上面相同,n的取值为原数中左边第一个不为0的数字前面所有的0的个数(包括小数点前面的0)。

    在Java语言中,浮点类型有float和double两种,分别代表单精度和双精度的数值。精度是指描述一个数值的准确程度,在数学运算中,经常会用到近似数,近似数与原数值非常相近,但又不完全符合原数值,只能说在某种程度上近似。精度与近似数相似,也是用一个与原数值非常相近的数代替原来的数值。

    前面说过存储一个数值所用的字节越多,其精度越高,数值范围也越大。由此看来,精度与存储字节数密切相关,float类型的存储空间是4个字节,其表示的值范围约为10-38到1038,double类型的存储空间是8个字节,其表示的值范围约为10-308到10308,float存储数值的精度和范围要小于double存储数值的精度和范围。因此,float是单精度数值,double是双精度数值。

    ccd0f2fa3241652d2acd07571c11df29.png

    float变量可按如下方式声明:

    3e01cb36c2fe5b9cc4526c4dc9f1ccc9.png

    double变量可按如下方式声明:

    d99bbf6edaa68d6c6cae1ea02c75c68c.png

    数值赋值给float变量时,数值尾部要加上小写“f”或大写“F”声明为float数值,不然编译器会给出“可能损失精度的错误”如下图所示。因为在Java语言中,带小数的数值默认为是double类型,double类型转换为float类型,自然要损失精度了。

    3080c95ddcee1699521fe6b0ecb6de6e.png

    在 Java 程序中使用浮点数和小数时,不能假定浮点计算一定产生整型或精确的结果,浮点数不是精确值,使用它们会导致舍入误差。

    展开全文
  • 3.浮点运算加法乘法 3.1加法 3.2乘法 1.实数数的表示 参考深入理解C语言-03-有符号数,定点数,浮点数 1.1定点数 一般在没有FPU寄存器的嵌入式系统中使用比较多。比如常见的32位系统中,将高16位作为整数...
  • AD708 极高精度通道、芯片运算放大器
  • 下面就来讲讲关于浮点数中,单精度双精度、多精度混合精度计算的区别。1关于圆周率 π我们提到圆周率 π 的时候,它有很多种表达方式,既可以用数学常数3.14159表示,也可以用一长串10的二进制长串表示。...
  • C语言 单精度和双精度实数输出

    千次阅读 2019-02-04 10:50:26
    C语言 单精度和双精度实数输出 有意义数字无意义数字的演示
  • 编排 | strongerHuang微信公众号|嵌入式专栏我们学过数学,都知道有理数无理数,然后在有理数中有一类叫浮点数的...下面就来讲讲关于浮点数中,单精度双精度、多精度混合精度计算的区别。嵌入式专栏1关于圆周...
  • MCU: STM32F767,启动硬件双精度浮点运算协处理器 IDE: Keil RVMDK V5.21.1.0 测试方法 浮点数0.1分别以单精度双精度累加1000000次,打印输出累加结果。 测试代码 double dVal = 0; float fVal = 0; for(int i ...
  • 实际上,任何精度的浮点运算也可以像BigInteger那样计算,可以用多个浮点数据表示更高精度的浮点数据。而这就要求实现带余数的浮点四则运算。 带余数的浮点四则运算的定义: 加法减法,余数结果的能精确表示...
  •  作为美国国家半导体LMP高精度放大器系列中的新成员,最新推出的LMP7731组装与LMP7732组装高精度运算放大器的输入电压噪声只有2.9nV/sqrtHz,中频噪声转角仅为3Hz,而0Hz~10Hz的峰值噪声电压也只有78nVpp,...
  • 双精度单精度和半精度

    千次阅读 2018-11-20 19:42:11
    浮点数是计算机上最常用的数据类型之...半精度是英伟达在2002年搞出来的,双精度和单精度是为了计算,而半精度更多是为了降低数据传输存储成本。 很多场景对于精度要求也没那么高,例如分布式深度学习里面,如果...
  • 关于matlab的单精度双精度

    千次阅读 2021-04-18 14:51:49
    在matlab中有这么两个函数hex2num(str),将16进制字符串str(默认双精度)转换成一个数(如果加一个类型转换可以转换为单精度hex2num(single(str))num2hex(num),将一个双精度的数num(默认)装换成16进制字符串(当然也...
  •  作为美国国家半导体LMP高精度放大器系列中的新成员,最新推出的LMP7731组装与LMP7732组装高精度运算放大器的输入电压噪声只有2.9nV/sqrtHz,中频噪声转角仅为3Hz,而0Hz~10Hz的峰值噪声电压也只有78nVpp,...
  • 单精度和双精度的区别

    万次阅读 多人点赞 2019-02-26 16:56:24
    1、单精度和双精度的字节数不同。前者占4个字节;后者占8个字节。 2、单精度和双精度有效数字位数不同。前者为8位;后者为16位。 3、单精度和双精度表示的数的范围不同。前者的数值范围在-3.40E+38 到 +3.40E+...
  • 单精度和双精度问题

    千次阅读 2020-08-24 10:46:54
    一,什么是单精度和双精度 单精度数(float)是指计算机表达实数近似值的一种方式。VB中Single(单精度浮点型)变量存储为 IEEE 32 位(4 个字节)浮点数值的形式,它的范围在负数的时候是从 -3.402823E38 到 -1....
  • 创建双精度数据首先创建一些数据,默认情况下为双精度。Ad = [1 2 0; 2 5 -1; 4 10 -1]Ad = 3×31 2 02 5 -14 10 -1转换为单精度可以使用 single 函数将数据...创建单精度一此外,也可以分别使用函数创建单精度...
  • 单精度float与双精度double

    千次阅读 2020-01-31 17:07:01
    单精度 双精度单精度,也即float,一般在计算机中存储占用4字节,也32位,有效位数为7位;双精度(double)在计算机中存储占用8字节,64位,有效位数为16位。 IEEE754规范: 单精度格式:1位符号,8位指数,23...
  • 汇编语言,双精度加法运算

    千次阅读 2019-12-11 08:57:58
    要求计算X+Y=Z,将结果Z输出到屏幕上,其中X=001565A0H,Y=0021B79EH。实验利用累加器AX,先求低十六位,并存入地址存储单元,后求高16位,再存入高址存储单元。由于地位可能向高位有进位...二进制双精度加法运算...
  • 之前服务器环境使用的是NVIDIA的Tesla P4的环境,程序运行没有问题,但是换成Tesla M40,程序就算就出现较大的偏差。 大致原因是M40是单精度的...解决方式是模型训练时,指明单精度运算做训练: 如: grayPix = (...
  • 单精度浮点数和双精度浮点数Here you will learn about difference between float and double i.e. float vs double. 在这里,您将了解floatdouble的区别,即float vs double。 These are two commonly used ...
  •  作为美国国家半导体LMP高精度放大器系列中的新成员,最新推出的LMP7731组装与LMP7732组装高精度运算放大器的输入电压噪声只有2.9nV/sqrtHz,中频噪声转角仅为3Hz,而0Hz~10Hz的峰值噪声电压也只有78nVpp,...
  • 单精度浮点数(float)与双精度浮点数(double)的区别 单精度浮点数(float)与双精度浮点数(double)的区别如下: (1)在内存中占有的字节数不同 •单精度浮点数在机内占4个字节 •双精度浮点数在机内占8个字节 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 66,171
精华内容 26,468
关键字:

双精度和单精度的运算

友情链接: FusionCharts.rar