要float和double数据类型有什么用?

时间:2023-01-10 09:32:12
做了几天程序开发有些细节总是被我们忽视。
double d = 10 - 9.9,d等于0.0999999999999996。float f = 10f - 9.9f,f等于0.1000004。这个大路边的减法结果都不对,要double和float类型干嘛??我要正确实现0.1=10 - 9.9我该怎么办?只能用10m-9.9m????

问题一
double d = 10 - 9.9,d等于0.0999999999999996,为什么?
float f = 10f - 9.9f,f等于0.1000004,为什么?

问题二
如上基本的减法结果都不对,要float和double数据类型有什么用?

20 个解决方案

#1


float f=0.4;
if(f==0.4)
cout<<"OK"<<endl; 
因为float f=0.4;实际上f的值是0.40000001,并不是0.4
当进行f==0.4运算时,两数并不相等(这里的0.4其实是double类型的0.40000000000000002)

而如果是double b = 0.4;//其实b的值是0.40000000000000002
执行if(b==0.4)时,两值相等(因为这里的0.4其实是double型,值为0.40000000000000002)

其实还可以做这样一个尝试:
float f=0.236;其实f的值是0.236000000
double b = 0.236;其实b的值是0.23599999999999999
这是因为浮点型数数据的精度问题导致我们看到的和实际的数是不同的

float是32位,double是64位
float32位中,有1位符号位,8位指数位,23位尾数为
double64位中,1位符号位,11位指数位,52位尾数位
取值范围看指数部分
float是有符号型,其中,8位指数位,2^8=(-128—127),因此实际的范围是-2^128—2^127,约为-3.4E38—3.4E38
同理double范围约是-1.7E308—1.7E308,
精度是看尾数部分
float尾数位23位,2^23=8.3E6,7位,所以不同的编译器规定不同,有些是7位,有些8位
double尾数52位,2^52=4.5E15,15位,所以double的有效位数是15位

#2


楼主不是计算机专业毕业的?假如不幸是的话太对不起你的学费了,假如不是赶紧回去补习去,做这行连这些最基础的知识都不学是没前途的...

IEEE 754浮点数是国际标准,是最最基础的计算机数据结构之一...浮点数有误差也是必然的,即使是如decimal之类高精度的数据类型也是有误差的...这是由无理数的特性与存储器的特性决定的...

而浮点数的好处是存储空间小,float只占4字节,double只占8字节...相应的高精度数据类型占用空间更大,如decimal要占16字节...

#3


我喜欢楼上的专业人士,我是信息管理与信息系统专业,我正在回去补习的路上,希望得到您的帮助……


希望您能回答的细致一点,我从您的回答中找不到答案,我感觉很多如我一样的人也从您的回复中找不到答案。为什么无理数的特性和存储器的特性就决定了这个误差?请您以细化到代码的态度给讲解一下,不胜感激。请您针对我上边的问题,回答。


多谢多谢

#4


谢谢1楼详细的回复,您写的这些有几个字节存储,有效位我都明白。如您所举例为什么“因为float f=0.4;实际上f的值是0.40000001,并不是0.4“???
我是用C#可能和你的不一样

多谢

#5


引用 4 楼 huadupi 的回复:
谢谢1楼详细的回复,您写的这些有几个字节存储,有效位我都明白。如您所举例为什么“因为float f=0.4;实际上f的值是0.40000001,并不是0.4“???
我是用C#可能和你的不一样

多谢

老V不在,还是我替他来回答吧,你只要思考两个问题就行
1、1~100之间有多少个整数?
2、1~100之间有多少个小数?

对于问题1,答案是明确的,1~100间有100个整数,而1~100间则有无限个小数。
这就是整型(int)与浮点型(float)之间的区别,整型是精确表达的,而浮点型则是表示一个大概的不准确的值。你想想一个float有多大?撑死4个byte,4个byte又能表达多少种状态?而1~100间又有多少个小数?不要说1~100,如果真的精确描述,一个float连0~1之间的小数都描述不完。正是由于这种无理数的特性(无穷尽)以及数据在计算机内存储的特性(有限长度)所以导致浮点数必然是不精确的,既然是不精确自己就会有误差,LZ你明白了么?这应该是初入门就该知道的事情。。 。。

#6


引用 4 楼 huadupi 的回复:
谢谢1楼详细的回复,您写的这些有几个字节存储,有效位我都明白。如您所举例为什么“因为float f=0.4;实际上f的值是0.40000001,并不是0.4“???
我是用C#可能和你的不一样

多谢

什么不一样,IEEE 754是标准.. ..

#7


唉,这还需要讲解啊...不过Laputa_Island解释的很清楚了...

无理数特性是初中数学知识,存储器特性和整型数及浮点数数据类型是计算机专业一年级课程微机组成原理知识...好好补习基础吧...

#8


楼主的问题很容易解决嘛。。。

既然 float 跟 double 都不能解决楼主的问题,就自己写一个 floatEx or doubleEx 数据类型出来就是。。

为什么非要吊死在 float or double 这棵树上呢。

#9


该回复于2011-04-11 15:50:52被版主删除

#10


引用 5 楼 laputa_island 的回复:
引用 4 楼 huadupi 的回复:
谢谢1楼详细的回复,您写的这些有几个字节存储,有效位我都明白。如您所举例为什么“因为float f=0.4;实际上f的值是0.40000001,并不是0.4“???
我是用C#可能和你的不一样

多谢

老V不在,还是我替他来回答吧,你只要思考两个问题就行
1、1~100之间有多少个整数?
2、1~100之间有多少个小数?

对于问题1,……

谢谢您的精彩讲解,通过您的讲解我确实理解了不少。
举个例子:
环境:C#
float f2 = 9.9f
上代码在编译成MSIL后会是如下:
IL_0001: ldc.r4 9.8999996,ldc.r4是说这是个4字节的浮点数
我是想知道9.9怎么按照IEEE754标准存储后就变成了9.8999996
多谢多谢

#11


引用 7 楼 vrhero 的回复:
唉,这还需要讲解啊...不过Laputa_Island解释的很清楚了...

无理数特性是初中数学知识,存储器特性和整型数及浮点数数据类型是计算机专业一年级课程微机组成原理知识...好好补习基础吧...

多谢,我是初学者,更是初学者的心态,希望您理解
我不算是真正的计算机专业,我上面说了是“信息管理与信息系统”专业,《微机组成原理》确实没学过,见笑了,赶紧往回补。

#12


引用 8 楼 cgabriel 的回复:
楼主的问题很容易解决嘛。。。

既然 float 跟 double 都不能解决楼主的问题,就自己写一个 floatEx or doubleEx 数据类型出来就是。。

为什么非要吊死在 float or double 这棵树上呢。

您是来打酱油的,不是在一棵树上吊死,我不理解就是不理解,学知识不能一知半解。给您出个题,你将浮点型9.9按照IEEE754标准存储后得到不精确结果,您把过程推理一下。

#13


9.9转化为二进制,写成1.xxxxxxxx乘2的xxxxxxxx次方,按照ieee754标准就可以了

#14


9.9 转换为二进制
1.00111100110011001100110011001100110011001100110011... 乘 2 的 11(十进制3)次方,无限循环小数

要float和double数据类型有什么用?

短 0    10000010 00111100110011001100110
长 0 10000000010 0011110011001100110011001100110011001100110011001101
10000010(2)为127+3=130
10000000010(2)为1023+3=1026

用16进制,高位在后显示就是
CD-CC-CC-CC-CC-CC-23-40
66-66-1E-41


        Dim d As Double = 9.9
        Dim f As Single = 9.9

        Dim ad = System.BitConverter.GetBytes(d)
        Dim af = System.BitConverter.GetBytes(f)

        Console.WriteLine(System.BitConverter.ToString(ad))
        Console.WriteLine(System.BitConverter.ToString(af))

#15


其实IEEE 754是一套认定的标准,为什么存储9.9的时候是按照9.8999996存储的,规定的呗~,你存一下0.5看一下是什么结果?

IEEE 754 其实是一套存储数据的方法,可以把范围内任意的小数存储到有限的空间里面,既然小数是任意无限,存储空间是有限的 ,那就必然存在着大部分数存储的是粗略不准确的结果,9.9恰好无法准确存储,仅此而已。对于判断浮点型是否相等,并不是用==,而是使用看它们之间的差,只要相差的足够小,就认为他们是相等的。

#16


你不要觉得9.9是一个很小的数,怎么float连这个也存储不了?计算机不是按照10进制去思考的,它是按照2进制去思考的。你把9.9转换成2进制,你看看它的位数有多大。你把0.5转换成2进制再看看。

#17


无奈了,LZ总共20分,LS几位都是狠人,不晓得能捡到几分。。。

#18


循环小数可以用分数表示

0.33333333..... 用1/3表示 在三进制里,就是0.1 ,不会循环了。

上面说的0.5,其实是可以准确表达的,0.5就是二进制的0.1,或者说是1.0乘2的-1次方
0 01111111110 0000000000000000000000000000000000000000000000000000

#19


受教...

#20


要float和double数据类型有什么用?

#1


float f=0.4;
if(f==0.4)
cout<<"OK"<<endl; 
因为float f=0.4;实际上f的值是0.40000001,并不是0.4
当进行f==0.4运算时,两数并不相等(这里的0.4其实是double类型的0.40000000000000002)

而如果是double b = 0.4;//其实b的值是0.40000000000000002
执行if(b==0.4)时,两值相等(因为这里的0.4其实是double型,值为0.40000000000000002)

其实还可以做这样一个尝试:
float f=0.236;其实f的值是0.236000000
double b = 0.236;其实b的值是0.23599999999999999
这是因为浮点型数数据的精度问题导致我们看到的和实际的数是不同的

float是32位,double是64位
float32位中,有1位符号位,8位指数位,23位尾数为
double64位中,1位符号位,11位指数位,52位尾数位
取值范围看指数部分
float是有符号型,其中,8位指数位,2^8=(-128—127),因此实际的范围是-2^128—2^127,约为-3.4E38—3.4E38
同理double范围约是-1.7E308—1.7E308,
精度是看尾数部分
float尾数位23位,2^23=8.3E6,7位,所以不同的编译器规定不同,有些是7位,有些8位
double尾数52位,2^52=4.5E15,15位,所以double的有效位数是15位

#2


楼主不是计算机专业毕业的?假如不幸是的话太对不起你的学费了,假如不是赶紧回去补习去,做这行连这些最基础的知识都不学是没前途的...

IEEE 754浮点数是国际标准,是最最基础的计算机数据结构之一...浮点数有误差也是必然的,即使是如decimal之类高精度的数据类型也是有误差的...这是由无理数的特性与存储器的特性决定的...

而浮点数的好处是存储空间小,float只占4字节,double只占8字节...相应的高精度数据类型占用空间更大,如decimal要占16字节...

#3


我喜欢楼上的专业人士,我是信息管理与信息系统专业,我正在回去补习的路上,希望得到您的帮助……


希望您能回答的细致一点,我从您的回答中找不到答案,我感觉很多如我一样的人也从您的回复中找不到答案。为什么无理数的特性和存储器的特性就决定了这个误差?请您以细化到代码的态度给讲解一下,不胜感激。请您针对我上边的问题,回答。


多谢多谢

#4


谢谢1楼详细的回复,您写的这些有几个字节存储,有效位我都明白。如您所举例为什么“因为float f=0.4;实际上f的值是0.40000001,并不是0.4“???
我是用C#可能和你的不一样

多谢

#5


引用 4 楼 huadupi 的回复:
谢谢1楼详细的回复,您写的这些有几个字节存储,有效位我都明白。如您所举例为什么“因为float f=0.4;实际上f的值是0.40000001,并不是0.4“???
我是用C#可能和你的不一样

多谢

老V不在,还是我替他来回答吧,你只要思考两个问题就行
1、1~100之间有多少个整数?
2、1~100之间有多少个小数?

对于问题1,答案是明确的,1~100间有100个整数,而1~100间则有无限个小数。
这就是整型(int)与浮点型(float)之间的区别,整型是精确表达的,而浮点型则是表示一个大概的不准确的值。你想想一个float有多大?撑死4个byte,4个byte又能表达多少种状态?而1~100间又有多少个小数?不要说1~100,如果真的精确描述,一个float连0~1之间的小数都描述不完。正是由于这种无理数的特性(无穷尽)以及数据在计算机内存储的特性(有限长度)所以导致浮点数必然是不精确的,既然是不精确自己就会有误差,LZ你明白了么?这应该是初入门就该知道的事情。。 。。

#6


引用 4 楼 huadupi 的回复:
谢谢1楼详细的回复,您写的这些有几个字节存储,有效位我都明白。如您所举例为什么“因为float f=0.4;实际上f的值是0.40000001,并不是0.4“???
我是用C#可能和你的不一样

多谢

什么不一样,IEEE 754是标准.. ..

#7


唉,这还需要讲解啊...不过Laputa_Island解释的很清楚了...

无理数特性是初中数学知识,存储器特性和整型数及浮点数数据类型是计算机专业一年级课程微机组成原理知识...好好补习基础吧...

#8


楼主的问题很容易解决嘛。。。

既然 float 跟 double 都不能解决楼主的问题,就自己写一个 floatEx or doubleEx 数据类型出来就是。。

为什么非要吊死在 float or double 这棵树上呢。

#9


该回复于2011-04-11 15:50:52被版主删除

#10


引用 5 楼 laputa_island 的回复:
引用 4 楼 huadupi 的回复:
谢谢1楼详细的回复,您写的这些有几个字节存储,有效位我都明白。如您所举例为什么“因为float f=0.4;实际上f的值是0.40000001,并不是0.4“???
我是用C#可能和你的不一样

多谢

老V不在,还是我替他来回答吧,你只要思考两个问题就行
1、1~100之间有多少个整数?
2、1~100之间有多少个小数?

对于问题1,……

谢谢您的精彩讲解,通过您的讲解我确实理解了不少。
举个例子:
环境:C#
float f2 = 9.9f
上代码在编译成MSIL后会是如下:
IL_0001: ldc.r4 9.8999996,ldc.r4是说这是个4字节的浮点数
我是想知道9.9怎么按照IEEE754标准存储后就变成了9.8999996
多谢多谢

#11


引用 7 楼 vrhero 的回复:
唉,这还需要讲解啊...不过Laputa_Island解释的很清楚了...

无理数特性是初中数学知识,存储器特性和整型数及浮点数数据类型是计算机专业一年级课程微机组成原理知识...好好补习基础吧...

多谢,我是初学者,更是初学者的心态,希望您理解
我不算是真正的计算机专业,我上面说了是“信息管理与信息系统”专业,《微机组成原理》确实没学过,见笑了,赶紧往回补。

#12


引用 8 楼 cgabriel 的回复:
楼主的问题很容易解决嘛。。。

既然 float 跟 double 都不能解决楼主的问题,就自己写一个 floatEx or doubleEx 数据类型出来就是。。

为什么非要吊死在 float or double 这棵树上呢。

您是来打酱油的,不是在一棵树上吊死,我不理解就是不理解,学知识不能一知半解。给您出个题,你将浮点型9.9按照IEEE754标准存储后得到不精确结果,您把过程推理一下。

#13


9.9转化为二进制,写成1.xxxxxxxx乘2的xxxxxxxx次方,按照ieee754标准就可以了

#14


9.9 转换为二进制
1.00111100110011001100110011001100110011001100110011... 乘 2 的 11(十进制3)次方,无限循环小数

要float和double数据类型有什么用?

短 0    10000010 00111100110011001100110
长 0 10000000010 0011110011001100110011001100110011001100110011001101
10000010(2)为127+3=130
10000000010(2)为1023+3=1026

用16进制,高位在后显示就是
CD-CC-CC-CC-CC-CC-23-40
66-66-1E-41


        Dim d As Double = 9.9
        Dim f As Single = 9.9

        Dim ad = System.BitConverter.GetBytes(d)
        Dim af = System.BitConverter.GetBytes(f)

        Console.WriteLine(System.BitConverter.ToString(ad))
        Console.WriteLine(System.BitConverter.ToString(af))

#15


其实IEEE 754是一套认定的标准,为什么存储9.9的时候是按照9.8999996存储的,规定的呗~,你存一下0.5看一下是什么结果?

IEEE 754 其实是一套存储数据的方法,可以把范围内任意的小数存储到有限的空间里面,既然小数是任意无限,存储空间是有限的 ,那就必然存在着大部分数存储的是粗略不准确的结果,9.9恰好无法准确存储,仅此而已。对于判断浮点型是否相等,并不是用==,而是使用看它们之间的差,只要相差的足够小,就认为他们是相等的。

#16


你不要觉得9.9是一个很小的数,怎么float连这个也存储不了?计算机不是按照10进制去思考的,它是按照2进制去思考的。你把9.9转换成2进制,你看看它的位数有多大。你把0.5转换成2进制再看看。

#17


无奈了,LZ总共20分,LS几位都是狠人,不晓得能捡到几分。。。

#18


循环小数可以用分数表示

0.33333333..... 用1/3表示 在三进制里,就是0.1 ,不会循环了。

上面说的0.5,其实是可以准确表达的,0.5就是二进制的0.1,或者说是1.0乘2的-1次方
0 01111111110 0000000000000000000000000000000000000000000000000000

#19


受教...

#20


要float和double数据类型有什么用?

#21