豆渣生吃猪会中毒吗:100分求救!cdbl转换精度的问题!

来源:百度文库 编辑:查人人中国名人网 时间:2024/04/28 05:51:39
我在vb中将前台录入的文本数据用cdbl转换为double类型存储,但是发现在转换大数时会发生数据精度溢出的问题
如cdbl(99999999999999.999999)后数据变为了100000000000000.000000.
请问高手如何解决这个问题,还是有其他的方式可以进行转换

看了你这个问题以后,我感到非常的感兴趣。之前从来没有想过这个问题。的确,double只能有15位有效数字。但如果需要储存更多的有效数位,该怎么办呢?基本上,有好几种方法可以解决,其中一种是自定义一个类型,如:
Public Type LongDouble
High As Long
Low As Long
Bit As Byte
End Type
然后再定义它们之间的算法。由于感觉这个问题非常有意思,我当即做了一段程序,不过没有使用自定义类型,而是使用了String来储存数据。String的最高长度是3000多位,已经足够使用了。但是VB不支持重载操作符,所以要使得它们可以相加减乘除,还是得费一定的心思的。现在只做了一个最简单的加法运算,经验证结果正确。如果楼主有兴趣,可以接着实现其减法、乘法和除法运算。

为调试以下代码,首先新建一个工程,移除其Form1,添加一个模块,在模块中粘贴以下代码

Option Explicit

Sub main()
Debug.Print Add("352341254215123.99999999999999", "4330.23")
End Sub

Public Function Add(ByVal LeftPara As String, ByVal RightPara As String) As String

Dim i As Long, r As String, a As Integer, b As Integer

'如果左右操作数有任何一个不是数字,则退出
If Not IsNumeric(LeftPara) Or Not IsNumeric(RightPara) Then
Add = ""
Exit Function
End If

'为简起见,不允许使用科学计数法
If InStr(UCase(LeftPara), "E") > 0 Or InStr(UCase(RightPara), "E") > 0 Then
Add = ""
Exit Function
End If
'为减少因用户输入带来的不正常现象,先把操作数两边的空格去掉
LeftPara = Trim(LeftPara)
RightPara = Trim(RightPara)

'为计算方便,先为整数的末尾加上一个小数点。不会影响有效位数的数目
If InStr(LeftPara, ".") = 0 Then LeftPara = LeftPara + "."
If InStr(RightPara, ".") = 0 Then RightPara = RightPara + "."

'对齐两个操作数的小数点,不足的位填“0”。这同样不会影响有效位数的数目
'对齐整数部分
If InStr(LeftPara, ".") < InStr(RightPara, ".") Then
LeftPara = Space(InStr(RightPara, ".") - InStr(LeftPara, ".")) + LeftPara
LeftPara = Replace(LeftPara, " ", "0")
ElseIf InStr(LeftPara, ".") > InStr(RightPara, ".") Then
RightPara = Space(InStr(LeftPara, ".") - InStr(RightPara, ".")) + RightPara
RightPara = Replace(RightPara, " ", "0")
End If
'对齐小数部分
If Len(LeftPara) - InStr(LeftPara, ".") < Len(RightPara) - InStr(RightPara, ".") Then
LeftPara = LeftPara + Space((Len(RightPara) - InStr(RightPara, ".")) - (Len(LeftPara) - InStr(LeftPara, ".")))
LeftPara = Replace(LeftPara, " ", "0")
ElseIf Len(LeftPara) - InStr(LeftPara, ".") > Len(RightPara) - InStr(RightPara, ".") Then
RightPara = RightPara + Space((Len(LeftPara) - InStr(LeftPara, ".")) - (Len(RightPara) - InStr(RightPara, ".")))
RightPara = Replace(RightPara, " ", "0")
End If

'此处检查对位正确性
'Debug.Print LeftPara, RightPara

'现在不足的位数全都是0了,这样,用一个For循环就可以逐位相加
'r用以记录结果,a记录是否有进位,b用以记录每一位相加的结果
r = "": a = 0
For i = Len(LeftPara) To 1 Step -1 '从最低位开始逐位相加
'如果碰到小数点,则不需要计算,但是需要为结果增加一个小数点
If Mid(LeftPara, i, 1) = "." Then
r = "." + r
Else
b = CInt(Mid(LeftPara, i, 1)) + CInt(Mid(RightPara, i, 1)) + a
'如果b>=10表示有进位
If b >= 10 Then
a = 1
b = b - 10
Else
a = 0
End If
r = CStr(b) + r
End If
Next
'如果最后有进位,应该在最高位加一个“1”
If a = 1 Then r = "1" + r
'去掉末尾多余的小数点
If Right(r, 1) = "." Then r = Left(r, Len(r) - 1)

'计算完毕,返回结果
Add = r
End Function

运行程序,结果将会在VB的立即窗口中显示。你也可以用MsgBox来代替Debug.Print,以用一个消息框来显示结果。试着修改Add函数的两个参数,看看结果是否正确?