Vb.Net attempt to divide by zero problem

Hi EE,
    I have a piece of code, it's working most of the time, however it some time throw 'attempt to divide by zero' error, although I did have a check for zero on the denominator before the divide, wonder what the problem is, if anyone has any idea please let me know.

                            Dim myDenominator As Decimal = (CDec(Math.Round(row("TotQty"), 2)) + CDec(Math.Round(row("DelQty"), 2)))
                            If (myDenominator <> 0) Then

                                Dim newStdCost As Decimal = (((CDec(Math.Round(row("TotQty"), 2)) * CDec(Math.Round(row("StdCost"), 2))) + (CDec(Math.Round(row("DelQty"), 2)) * CDec(Math.Round(row("DelCost"), 2))))) / myDenominator

End If

Open in new window

Who is Participating?
Jacques Bourgeois (James Burger)Connect With a Mentor PresidentCommented:
The Single is a 32-bit number. 16 for the integer part, 16 for the decimal. The number of decimals is thus fixed at 7.

The Double is a 64-bit number. 32 for the integer part, 32 for the decimal. The number of decimals is thus fixed at 15.

The Decimal is a 128-bit number. However, contrary to the other 2 types of floats, the number of bits assigned to the integer part and the decimal part is variable. If you have a value of 0, no bit is used for the integer part, and all of the 128 bits are used for the decimal part, giving you 28 decimal places. As the integer part grows, the number of bits available for the decimal part is reduced, an you thus lose decimal places. A very big number (either negative or positive) will thus have less decimal precision than a small one.

I do not know about the implementation details, but it is clear that this mechanism of having a variable lenght for the integer vs decimal parts of a value involves some internal manipulations that are not necessary in a Double that has a fixed memory footprint for the 2 values. What is clear also is that the Decimal type incurs a hit on performance. So, unless you really need the extra precision (over 15 decimals), you are better to stay clear of that type.

Now, a question of my own. I would be glad to have somebody jump in and explain that to me.

The documentation for Decimal states that the Decimal type "is particularly suitable for calculations, such as financial, that require a large number of digits but cannot tolerate rounding errors". This is confirmed somewhat by the fact that when you convert a VB6 application to .NET, the old Currency type (that is not available anymore) is converted to Decimal. I greatly suspect that your use of the Decimal type could come from such a conversion.

But although I never had to code financial applications, in my experience most financial operations round off at 4 decimals (this is what the old Currency type did). When I bought my house, I checked the interests charged by the bank and came out with a higher amount than the bank did. It made a difference of $25 a month on my paiement. I was working with Single values, 7 decimals. When I adjusted to 4, I came out with only 1 cent of difference... and figure out who was getting the extra cent?

I know that some finalcial operations, such as currency exchange, round off at 5 decimals. So, why this statement about Decimal suitable for financial calculations. A Single is quite capable of working at that level, and a Double twice more so.

As far as I am concerned, Decimal could be useful for some scientific calculations, say at the level of the atom or the universe. But even there, it is often too much. I had to do something dealing with chemistry for a pharmacology company many years ago, and the Double, with its 15 decimals of precision, was enough for them.

So, could somebody tells me what types of financial operations would require the Decimal type?
Jacques Bourgeois (James Burger)PresidentCommented:
Do you absolutely need the precision of a Decimal?

When you assign the value to your denominator, you end up with only 2 decimal. And the multiplication ends up with 6 at most. There is no need for all the extras that the Decimal type provides.

Because the number of decimal places in the Decimal type is variable, Decimal values are handled in a special way compared to the more straightforward Single and Double type.

I would try removing all the CDec and work with a Double all the way. Convert only the result to Decimal if you really need that data type for other operations.
miketonnyAuthor Commented:
thanks James,
could you let me know how double and decimal are handled differently? i see this is a good chance of learning something I didn't know before.
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

ElrondCTConnect With a Mentor Commented:
Responding to the original question: Are you sure the problem is happening at the Dim newStdCost line? Is it giving you that line number in the stack trace, or is it stopping there in the debugger? If you view myDenominator, does it show 0? What's the point of having newStdCost defined inside an If/Then block that is only one line long? It's going to be out of scope as soon as the End If is hit. Or did you simply delete following lines in the If/Then block?

James, as a developer of financial applications, I can tell you that I use Decimal types for all of my currency values. The reason is that it's too easy for rounding errors to creep in otherwise. It may not seem like a big deal what's happening to that extra cent, but it makes accountants go crazy; they want numbers to tie out exactly. I go to a lot of effort to make sure that, for instance, if a one dollar asset is depreciated over three months, I get back to a dollar, not 99 cents. The other issue is that getting a spurious 1 millionth or whatever can cause comparisons to go haywire: if .33 + .37, because of the imprecision of floating point arithmetic, turns into .70000000000001, that doesn't equal .7, and you can run into really nasty debugging projects and extra verifications required all over the place. (Even more commonly at issue, .00000000001 <> 0.)

Decimal is a bit more processor-intensive, to be sure, but in my opinion it's well worth it. If the alternative is doing a Math.Round() call every time you add and subtract, you're probably ahead of the game.
Jacques Bourgeois (James Burger)PresidentCommented:
Thanks for the input Elrond.

I never had to deal with those precisions in my applications, where woodworkers often find that 1/64 is too much precision in my current project, and where money operations in my older projects were almost of the multiplying a quantity by a unit price and adding the taxes sort. And my own accoutant is OK as long as we follow the rounding rules of the canadian government that do not got further than a few decimals. My bank does not care either, interests on my 25 years mortgage were rounded out at the 4th decimal.

Having the input from a programmer who has another experience is always a good learning lesson.
miketonnyAuthor Commented:
thanks guys for all the input, really helped me understand the definition and difference between these two. appreciate all your help.
miketonnyAuthor Commented:
yes I'm sure it was the line throwing the error.
there are further calculations after that however none of them have a divide so i took them out in the post above.

the funny thing is it is not always throwing the error, happens 1 - 2 times everyday. i tried to record the product it had the issue and went back checked, everything looked normal.

maybe there's something else going wrong?
If you haven't gotten a stack trace or other message that specifically points to that line, then I'd be suspicious that there's something else happening. A Mod calculation, for instance, can also return a divide by zero error. There might be other things that don't come immediately to mind.

If you're getting it 1-2 times a day, I presume this is an application that's in production. Since it's intermittent, just running in debug won't likely help you much. But I think you need to get some debugging information out of the application. My first step would probably be to put the Dim newStdCost statement in a Try/Catch block. If the exception fires, display ALL the values that are in the calculation on that line. If you get the error and the Catch isn't triggered, it tells you that the problem is somewhere else; perhaps you can set up another Try/Catch block for the rest of the code and display enough information in the error message to tell you how far it got before crashing.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.