如何避免Excel VBA类型双数学运算中的内部计算错误?



从Excel 2007中,我在阅读本网站时想到了这个VBA代码:将十进制转换为二进制分数
主要目标是提出一个将小数转换为二进制表示的函数。
下面是我的代码:

Sub DTBfraction() ' Decimal to Binary
Dim myFraction As Double
Dim tmpDEC As Double, tmpPRO As Double, tmpREM As Double
Dim i As Long
Dim tmpSTRING As String, tmpBIT As String
myFraction = 0.8
tmpDEC = myFraction
Do
i = i + 1
tmpDEC = tmpDEC * 2
tmpPRO = Int(tmpDEC)
tmpREM = tmpDEC - tmpPRO
tmpBIT = IIf(tmpPRO >= 1, "1", "0")
tmpSTRING = tmpSTRING & tmpBIT
If i > 2000 Then Stop ' needed to prevent cases of infinite looping

Debug.Print i, myFraction, tmpDEC, tmpPRO, tmpREM

tmpDEC = tmpREM
Loop Until tmpREM <= 0

Debug.Print "0b0." & tmpSTRING
End Sub
Rem  Debug.Print  i  myFraction   tmpDEC            tmpPRO   tmpREM
Rem  Debug.Print  1     0.8        1.6                 1       0.6
Rem  Debug.Print  2     0.8        1.2                 1       0.2
Rem  Debug.Print  3     0.8        0.4                 0       0.4
Rem  Debug.Print  4     0.8        0.800000000000001   0       0.800000000000001
Rem  Debug.Print  5     0.8        1.6                 1       0.600000000000001
Rem  Debug.Print  6     0.8        1.2                 1       0.200000000000003
Rem  Debug.Print  7     0.8        0.400000000000006   0       0.400000000000006
' ...       up to 52 in that particular case
Rem  Debug.Print    0b0.1100110011001100110011001100110011001100110011001101

遇到的问题是,在第4次循环时,代码将计算0.800000000000001,而不是得到0.8,这创建了一个不希望的循环多次的行为,直到条件将终止循环,直到tmpREM达到一个非常小的值,它被认为是0。实际上,这个循环应该是无限的,因为tmpREM永远不会变为零。这是一个周期性的情况。

经过一些实验和测试,发现0.6 0.2 0.4的前3个tmpREM值不是。相反,它们稍微高一点,但在Debug上不显示。打印行,但如果执行测试(如tmpREM>0.6,实际上tmpREM = 0.6会显示一个False状态。

的目标是通过编程捕获这种情况,以便代码停止无限地输出1和0,但我的解决方案是一个业余的,没有功能。我试着用10^12乘以结果,做一个INT()然后再乘以10^12。这不是一个可行的解决方案。减法也不起作用,而不是0.8 VBA吐出0.799999999999。
我觉得解决方案在于防止计算错误输出0.80000000000001而不是0.8

一旦实现,我可能能够想出一个解决方案来检测周期性计算并阻止代码循环。在这一点上,我失去了想象力。因此,问题是:
我如何才能摆脱这个计算错误,使我得到0.8而不是0.800000000000001 ?

二进制中的某些数字有无限的"小数",非常类似于十进制中的1/3和1/7。这些数字不能精确地用二进制表示;其中之一是1/10

小数可以四舍五入到n位:

n = 1
numff = int (num * 10 ^ n + 0.5)/10 ^ n

…但是当你把n取到更大的数时,它也有限制;又是由于计算机的数值精度。

最新更新