当前位置:编程学习 > VB >>

VB浮点型数据计算无故错误--数据类型值得注意的地方

  同样可以作为浮点运算的数据类型:Currency、Double、Variant,但是却存在着一个致命的差异,Double、Variant虽然可以作为浮点型数据然而在小数位数比较大的时候却会出现计算结果错误的情况。如果我们使用Double、Variant类型的变量来存储浮点数,在进行如下运算的时候就会出现让人哭笑不得的结果:


源代码我就不写出来了,只把debug的内容弄出来。
ASj(j, k) - ASj(i - 1, k) * ASj(j, k) / zASj( i - 1, k) = ASj( 5 , 3 ) - ASj( 3 , 3 ) * ASj( 5 , 3 ) / ASj( 3 , 3 )=-28.0949824224992  -  48.0471540428252  *-28.0949824224992  /  48.0471540428252 =-3.5527136788005E-15 



上面的数据虽然小数点后面有一长串数字但是计算非常简单,其结果为0!然而计算的结果却为-3.5527136788005E-15,这就是Double、Variant所会产生的错误,然而如果我们用的数据类型是Currency那么就可以成功的得到0的结果! 至于原因我不知道,写这个帖子主要就是提醒各位同僚能借我前车之鉴,不要搞大头都找不到问题所在!一旦会出现位数较高的浮点数最好还是使用Currency!


希望哪位大侠有空的时候补充一下这个帖子讲讲造成这种差异的原因。 感谢分享经验
引用 1 楼 dbcontrols 的回复:
感谢分享经验
謝謝分享,共同進步! 调试未见LZ所说的情况:
Private Sub Command1_Click()
    Dim sj(4) As Double
    sj(0) = -28.0949824224992
    sj(1) = 48.0471540428252
    sj(2) = -28.0949824224992
    sj(3) = 48.0471540428252 '= -3.5527136788005E-15
    sj(4) = sj(0) - sj(1) * sj(2) / sj(3)
    Debug.Print sj(4)
End Sub

结果是:-3.5527136788005E-15 谢谢分享,VB对数据类型的支持的确是一大软肋 Double、Variant 用于浮点数运算。

Currency用于货币或定点数计算。

并非Currency就好于Double、Variant,要看工程用于的不同地方。

另外就楼主的数据测试Double无楼主所有说情况。

浮点数的误差来自低层10进制与2进制的转换很多时候是不能精确匹配的。
关于某些大侠说的不会出现错误我也碰到过,这个错误在我自己的笔记本上是不会出现的,但是在公司的电脑上会出现,因为两台电脑安装的VB都是同一个安装包,因此我估计原因可能出在硬件或者操作系统上,至于硬件我的笔记本和公司的电脑唯一的区别就是公司的电脑主板是VIA的芯片组,而我自己的电脑nForces的芯片。
引用 6 楼 chaingreat 的回复:
关于某些大侠说的不会出现错误我也碰到过,这个错误在我自己的笔记本上是不会出现的,但是在公司的电脑上会出现,因为两台电脑安装的VB都是同一个安装包,因此我估计原因可能出在硬件或者操作系统上,至于硬件我的笔记本和公司的电脑唯一的区别就是公司的电脑主板是VIA的芯片组,而我自己的电脑nForces的芯片。

这个跟主板芯片组似乎无关,我只记得奔腾的年代出现过浮点数计算错误(CPU)。难道历史重演? 如果你学过数值计算的话 你就会知道 
计算机是不能完全表示浮点数的
而且能表示的只是其中的一小部分

这种由于计算机本身造成的误差叫做舍入误差 只能留个心眼了 浮点数本身就不是精确的,会有微小误差 看看MSDN的说法:
如果变量包含小数,则可将它们声明为 Single、Double 或 Currency 变量。Currency 数据类型支持小数点右面 4 位和小数点左面 15 位;它是一个精确的定点数据类型,适用于货币计算。浮点(Single 和 Double)数比 Currency 的有效范围大得多,但有可能产生小的进位误差。
计算机以尽可能小的值表示0,有误差在所难免,format一下问题不大. IEEE 754 浮点数的表示精度探讨
参见:http://blog.csdn.net/chinayuppie/archive/2009/06/15/4269754.aspx 用10进制小数不能精确表示某些三进制小数0.1(3)=0.33333333333……(10)
同理,用二进制小数也不能精确表示某些10进制小数。

Single
(单精度浮点型) 4 个字节 负数时从 -3.402823E38 到 -1.401298E-45;正数时从 1.401298E-45 到 3.402823E38
Double
(双精度浮点型) 8 个字节 负数时从 -1.79769313486232E308 到
-4.94065645841247E-324;正数时从4.94065645841247E-324 到 1.79769313486232E308
Currency
(变比整型) 8 个字节 从 -922,337,203,685,477.5808 到 922,337,203,685,477.5807
Decimal 14 个字节 没有小数点时为 +/-79,228,162,514,264,337,593,543,950,335,而小数点右边有 28 位数时为 +/-7.9228162514264337593543950335;最小的非零值为 +/-0.0000000000000000000000000001
Variant
(数字) 16 个字节 任何数字值,最大可达 Double 的范围 

内部事情。。用的时候看情况而定。
补充:VB ,  基础类
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,