Solved

Vb.Net attempt to divide by zero problem

Posted on 2013-05-16
8
480 Views
Last Modified: 2013-05-23
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

0
Comment
Question by:miketonny
  • 3
  • 3
  • 2
8 Comments
 
LVL 40

Expert Comment

by:Jacques Bourgeois (James Burger)
Comment Utility
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.
0
 
LVL 2

Author Comment

by:miketonny
Comment Utility
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.
0
 
LVL 40

Accepted Solution

by:
Jacques Bourgeois (James Burger) earned 300 total points
Comment Utility
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?
0
 
LVL 20

Assisted Solution

by:ElrondCT
ElrondCT earned 200 total points
Comment Utility
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.
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 40

Expert Comment

by:Jacques Bourgeois (James Burger)
Comment Utility
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.
0
 
LVL 2

Author Comment

by:miketonny
Comment Utility
thanks guys for all the input, really helped me understand the definition and difference between these two. appreciate all your help.
0
 
LVL 2

Author Comment

by:miketonny
Comment Utility
ElrondCT,
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?
0
 
LVL 20

Expert Comment

by:ElrondCT
Comment Utility
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.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

A while ago, I was working on a Windows Forms application and I needed a special label control with reflection (glass) effect to show some titles in a stylish way. I've always enjoyed working with graphics, but it's never too clever to re-invent …
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now