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))))) / myDenominatorEnd If

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.

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.

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

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

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.

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.

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.

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

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Well, all of us have seen the multiple EXCEL.EXE's in task manager that won't die even if you call the .close, .dispose methods. Try this method to kill any excels in memory. You can copy the kill function to create a check function and replace the …

Introduction
Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares.
The application is written in VB.NET targeting the .NET framework 2.0.
The source code and the compiled programs have been in…

Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…

Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …