谨慎使用单精度双精度数值类型

谨慎使用单精度双精度数值类型,第1张

谨慎使用单精度双精度数值类型,第2张

单精度和双精度数值类型最早出现在C语言(一种通用语言)中。在C语言中,单精度类型称为浮点类型。顾名思义,浮点小数点是用来存储数据的。这两种数据类型最早是为科学计算而产生的,它们可以为科学计算提供足够高的精度来存储精度要求高的值。但同时,他也完全符合科学计算中的数值概念:

当我们比较两根棍子的长度时,一种方法是并排比较,另一种方法是分别测量长度。但事实上,世界上没有两根长度完全一样的棍子。我们的测量精度受到人类视觉能力和测量工具精度的限制。从这个意义上来说,判断两根棍子是不是一样长是没有意义的,因为结果一定是假的,但是我们可以比较哪根更长或者更短。这个例子很好地总结了单/双精度数值类型的最初设计意图和意义。

基于以上知识,单精度/双精度数值型从设计之初就不是精确的数值型。它只保证在这个数值类型的精度内是准确的,而不超出精度。例如,如果一个数值是5.1,则存储在单精度/双精度数值中的实际值可能是5.1000 . 00000000000005。我们可以用两种方式来解释这种现象:

简单解释方法:

您可以尝试在任何控件的属性面板中将其宽度设置为3.2厘米。当你输入完之后,你会发现无论你怎么改,数值都会自动变成3.199CM,不能输入3.200CM,因为实际上电脑里存储的数值不是以CM为单位,而是以缇为单位,缇和CM的比值很高。计算机自动将其转换为最接近的“缇”值,然后转换为厘米并显示在属性面板上。这种乘法和除法,以及两次舍入,将导致错误。单精度/双精度也是类似的原理。实际上,存储二进制时,单精度/双精度采用的是相似分数的方法,这样的存储不可能是精确的。

深度讲解法:

让我们看看我们存储在数字媒体中的单精度/双精度值是什么样的。我们使用下面的代码来剖析单精度类型:

public Declare Sub copy memory Lib“kernel 32”别名“RtlMoveMemory”(目标为任意,源为任意,ByVal长度为Long)

public Sub float test()
Dim dbl var As Single

dbl var = 5.731/8
dblOutput dbl var

dbl var = dbl var * 2
dblOutput dbl var

dbl var = dbl var * 2
dblOutput dbl var

dbl var = dbl var * 2
dblOutput dbl var

dbl var = dbl var * 2
dblOutput dbl var

dbl var = dbl var * 2
dblOutput dbl var

末端接头

public Sub dblOutput(ByVal dbl var As Single)
Dim byt var(3)As Byte
Dim I As Integer,j As Integer
Dim strVar As String

CopyMemory ByVal VarPtr(bytVar(0))、ByVal VarPtr(dblVar)、4
strvar = dbl var & ":
for I = 3到0 Step -1
For j = 7到0 step-1
strvar = strvar &(byt var(I)和2 ^ j)/2 ^ j
next j
strvar = strvar & " "
next I打印strVar

end
运行后,我们得到输出结果(输出格式为左上右下):

716375:001111111 00110111 01100100 010111010
1.43275:001111111 10110111 01100100 01011010
2.8655:01000000000 00111 01100 0101010在这里,我们看到这六个数虽然完全不同,但它们的二进制存储却惊人的相似。我们看到红色标记的部分,每次加1。实际上,单精度数据类型是从高位的第一位作为正负标记位(绿色),第二位到第九位,是跨字节的有符号字节类型数据。该值决定小数点移动的方向和位数(红色),第10位到第32位保存一个整数(蓝色)。在存储过程中,计算机首先对输入值进行移位(乘以2再除以2),直到这个数的整数部分占据全部24位,然后将移位后的数字写入浮点部分(红色),移位后的结果写入整数部分(蓝色和绿色),小数部分被丢弃。评估的时候,是反向的过程。先按正负位和整数位求值,再按红色部分的整数移位(乘除以2的幂)。最后是我们得到的单精度值。双精度数值也是同样的原理,只不过位数多一些。

通过解剖单精度数值的二进制存储格式,我们可以清楚地看到,其实单精度/双精度的存储都得通过乘除来完成,其中必然有舍入。如果你的数值在除法中取整,那么你赋的初值很可能和你最终存储的值不完全相同,微小的差异并不违背单精度/双精度的设计目标。

当我们在数据库或VBA代码中使用单精度/双精度值时,也许你从界面上看不到区别,但在实际存储中,区别是真的存在的。当你进行相等比较时,系统只是简单的进行二进制比较,界面上体现不出来的细微差别在二进制比较前面的任何地方都看不到,所以你的相等比较返回一个意外的False。

结束语

本文介绍了单精度/双精度数据类型的本质和特点(优缺点)。通过对比和解剖,我们知道单精度/双精度其实存储的是一个近似值。浮点的特性决定了它可以存储很小的数,也可以存储很大的数。它的数据精度不是绝对值,而是存储值的百分比。如果存储10的100次方,误差可能是10的80次方。因此,单精度/双精度数据类型不能同等比较(或与数据库相关)。

如果需要进行等价比较或关联,那么有以下几种方案:

1.使用为准确性而设计的货币类型。
2。使用整型存储和代码移位。
3。在一定情况下可以储存在文字中。

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » 谨慎使用单精度双精度数值类型

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情