RE: When double precision isn't very precise

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Peter:
While the response from other writter is correct in advising that you should
not be using floating point calculations for financial analysis, you are also
correct that there is a bug in the floating point arithmetic in VB.Net. The
symptom is that when you add two double precision variables together and
assign the result to another double precision variable, the result may only
be accurate to single precision. The remaining digits are random. This
behavior does not occur all of the time however. It seems to depend on what
has preceeded the calculation. I have seen this in my own code under
repeatable conditions, and it has been verified by a co-worker who
encountered the same problem independently in a different program.

The code below is a simple subroutine that will test whether the error is
occurring. Just call this from anywhere in your program. I find that
sometimes this test routine passes, and sometimes it fails and traps an error
with the message box. I have not determined any way to determine if/when the
error will occur. This is truely a serious problem that makes VB inadequate
for certain types of engineering calculations where double precision is
important. I have tried converting some my code to use the Decimal data
type, but that actually made the problem worse. It is not practical to
convert my entire program to Decimal, so it is an unresolved problem at this
point.

Oddly, the problem seems related to the assignment of the value to a
variable. If you set a break point in this routine and inspect the
expression in the watch window it will be correct, but the value of the
variable that the expression is assigned to is not correct.


Public Shared Sub TestAddition()

Dim dummy1 As Double, dummy2 As Double, dummy3 As Double
Dim dummy4 As Double
Dim dummy5 As Double

dummy1 = 1.0 / 3.0
dummy2 = 1.0
dummy3 = dummy1 + dummy2 'should be 1.3333333333333333, but is
actually 1.3333333730697632

'Debug.Print(dummy3)

dummy4 = 1.0 + 1.0 / 3.0 'this produces the correct answer:
1.3333333333333333; therefore the problem seems to be with adding
double-precision variables, not literals

'Debug.Print(dummy4)

dummy5 = dummy3 - dummy4 'the difference between the correct and
incorrect answers

'Debug.Print(dummy5)

If dummy5 > 0.000000001 Then
MsgBox("round off error in vb")
End If

End Sub


"Peter B. Steiger" wrote:

I wrote a quick-and-dirty accounting routine that added up charges and
payments to show a running balance on someone's ledger. Our QA team
reported that it is producing the wrong balances, and sure enough it was.
The answers were coming back with umpteen decimal places written in
scientific notation, e.g. 1.23456E-9.

I thought I'd play it smart and wrote a function to do all the work in
integers - it receives the running balance and new amount, multiplies
them by 100 into integer variables, adds the two integers, and divides
the result by 100. It's stupid that I have to do this because our state-
of-the-art computer can't add two-place numbers together and come up with
the right answer, but at least it was an easy enough kludge.

Now it turns out it's also converting to integers wrong. For example,
with a balance of $595.17 added to $80.00, the new balance is $675.16
because it multiplied 595.17 * 100 and came up with... 59516.

The balance and amount are both double precision, so I did some testing:
Module FloatTest

Sub Main()

Dim nFloat1 As Single

Dim nFloat2 As Double

Dim nInt1 As Integer

Dim nInt2 As Integer



nFloat1 = 595.17

nInt1 = Int(nFloat1 * 100)

Console.WriteLine("Int of single " & nFloat1 & " * 100 is " & nInt1)

nFloat2 = 595.17

nInt2 = Int(nFloat2 * 100)

Console.WriteLine("Int of double " & nFloat2 & " * 100 is " & nInt2)

End Sub

End Module


The results? Multiply a single-precision number with two decimal places
by 100, and you get the right answer (in this case, 59517). Multiply a
double precision number by 100 and you get the wrong answer (59516).

I know FP math produced weird results on old CPUs (8086 through 80486),
but I would have thought for sure some processor genius would have fixed
the problem by now. Is this a known bug, or am I using the wrong data
types for my purposes, or what?

--
Peter B. Steiger
Cheyenne, WY
If you must reply by email, you can reach me by placing zeroes
where you see stars: wypbs.**1 at gmail.com.

.



Relevant Pages

  • Re: Precision
    ... Whether one does the subsequent calculations in internal ie integer format ... I have always used external format with Precision 4 since my ... floating point calcs which are done in binary have around 3% error albeit at ... positions it is IMPOSIBLE to have a result of 4 decimals with the 2 ...
    (comp.databases.pick)
  • Precision
    ... All my comments relate to common accounting practice in normal double-entry ... remember what the associated actuarial calculations were. ... again I would use floating point and isolate the programs. ... Change PRECISION 4 to 5 and you lost a leading significant digit. ...
    (comp.databases.pick)
  • Re: How to escape comparing floating-point numbers
    ... never a good idea to compare floating point numbers for equivilence. ... "No idea" is a little too strong, if you know the precision of the ... two intervals overlap, they might contain *actually* equal values. ... If you need to know the error when you are done with the calculations, ...
    (comp.programming)
  • Re: Precision
    ... It's the same if we use Precision, floating point, or ... positions it is IMPOSIBLE to have a result of 4 decimals with the 2 ... May be something wrong in the floating ... remember what the associated actuarial calculations were. ...
    (comp.databases.pick)
  • Re: Linear Algebra Challenge
    ... Since I'm using floating point, so I'll never be able to calculate one ... floating point math set to 99 digits. ... As close as I'm willing to wait if I use arbitrary precision. ... This mode is fast; when you select arbitry ...
    (comp.sys.hp48)