This function performs ASTM E29-93A standard rounding on real numbers for numbers containing 15 or less digits.
There are a lot of rounding functions out there that use VB's Int() command. They're fairly short and work to a point, but not always. Due to the way floating point numbers are handled, there can be errors such as 5.3435 being rounded to 5.344 but 5.3335 remaining 5.333.
If you are unfamiliar with the ASTM E29-93A standard, it states that numbers are to be rounded per the following conditions:
Note: X refers to the last digit to be retained and Y refers to the digit following X
1. If Y is greater than 5, increase X by one
2. If Y is less than 5, do NOT increase X
3. If Y is equal to 5 and any digits following Y are non-zero then increase X by one
4. If Y is equal to 5 and all digits following Y ARE equal to 0 and X is odd then increase X by one
5. If Y is equal to 5 and all digits following Y ARE equal to 0 and X is even then do NOT increase X
My code bypasses VB's built-in rounding features ((i.e. Int()) and performs the rounding manually, using various string and math techniques.
The latest version of the code can handle very large numbers (in theory, up to (2^32)/2 digits long!)
I've included an example project to show you how it works. Also, the project uses another one of my creations, cTextBox, a customized textbox control. I've included the cTextBox.ocx file, but you'll need to copy it to your Windows system directory and register it. Email me if you have any trouble with it.
Please let me know if you find any bugs or have any improvement ideas! Thanks.
Note: Due to the size or complexity of this submission, the author has submitted it as a .zip file to shorten your download time. Afterdownloading it, you will need a program like Winzip to decompress it.Virus note:All files are scanned once-a-day by Planet Source Code for viruses, but new viruses come
out every day, so no prevention program can catch 100% of them. For your own safety, please:
Re-scan downloaded files using your personal virus checker before using it.
NEVER, EVER run compiled files (.exe's, .ocx's, .dll's etc.)--only run source code.
Scan the source code with Minnow's Project Scanner
If you don't have a virus scanner, you can get one at many places on the net
Terms of Agreement:
By using this code, you agree to the following terms...
You may use
this code in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.
You MAY NOT redistribute this code (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.
You may link to this code from another website, but ONLY if it is not wrapped in a frame.
You will abide by any additional copyright restrictions which the author may have placed in the code or code's description.
When I run the routine against the number 6818.715, rounding to 2 places, it computes 6818.72 quite nicely. However, when I run it against 6818.735, it computes 6818.73, not 6818.74. Where it isn't computing the way I'd expect, the value of dblRightOfDecimalShifted is 734, with intOneBeyondLast being equal to 4. Since I'm truly clueless about the math behind dblRightOfDecimalShifted, is there a fix for this? (If this comment was disrespectful, please report it.)
When I run the routine using 6818.715 rounded to 2 places, it computes 6818.72, but when I send it 6818.735, it computes 6818.73, not 6818.72. When it doesn't work, the value of dblRightOfDecimalShifted is 734, with intOneBeyondLast equal to 4. Since I'm clueless about the math behind dblRightOfDecimalShifted, is there a fix to the formula that will always cause 5 or higher in the first dropped position to round up? (If this comment was disrespectful, please report it.)
Ok, I made some changes. I was actually aware of some of the problems for awhile, but I've been busy with other projects. Before, I was splitting the whole and decimal parts of the number using some shifting techniques, but the VB "fix" command was causing trouble. Now, I'm parsing the number using some more string functions (I know those won't change the numbers). Also, Patrice commented that 5 or higher in the first dropped position should always round up. This is not the case when using the ASTM E29-93A standard. According to the standard, when the first dropped position is 5, you only round up if the last kept position is odd or if there are any non-zero digits following the first dropped position. (If this comment was disrespectful, please report it.)
New Version - Now includes ability to check for Scientific Notation when rounding. Sometimes VB, when converting a double to a string, passes a number like 2.483957E-04. This was causing all sorts of problems, so I added some code to take care of that. It's bypassed by default, but can be turned on via parameter passed into function call. (If this comment was disrespectful, please report it.)
I know this was submitted months ago, is there something wrong with the VB Function Round()? I've been using it and would hate to learn that is wasn't accurate. (If this comment was disrespectful, please report it.)
Most of the time, Round works just fine; however, during testing, we discovered that it sometimes rounds incorrectly. These are generally very minor and rare errors; however, my company needed to be able to guarantee rounding accuracy, so we wrote our own function. (If this comment was disrespectful, please report it.)
Add Your Feedback
Your feedback will be posted below and an email sent to
the author. Please remember that the author was kind enough to
share this with you, so any criticisms must be stated politely, or they
will be deleted. (For feedback not related to this particular code, please
click here instead.)