VBA Ultimate rounding - vba

I've read much about rounding in Excel. I found out that VBA's Round() function uses "Bankers rounding" while Application.WorksheetFunction.Round() uses more or less "normal" rounding. But it didn't help me to understand this:
? Round(6.03499,2)
6.03
Why? I want to see 6.04, not 6.03! The trick is that
? Round(Round(6.03499,3),2)
6.04
I thought a bit and developed a subroutine like this:
Option Explicit
Function DoRound(ByVal value As Double, Optional ByVal numdigits As Integer = 0) As Double
Dim i As Integer
Dim res As Double
res = value
For i = 10 To numdigits Step -1
res = Application.Round(res, i)
Next i
DoRound = res
End Function
It works fine.
? DoRound(6.03499,2)
6.04
But it is not cool. Is there any built-in normal rounding in Excel?

If you round 6.03499 to 3 digits it will be 6.035 - which is correct.
If you round 6.03499 to 2 digits it will be 6.03 - which is correct
However - the example where you first round to 3 digits, then to 2 is also correct, by the following statement:
Round(6.03499, 3) gives 6.035
Round(6.035, 2) gives 6.04
If you want Round(6.03499, 2) to give 6.04 you have to use Application.WorksheetFunction.RoundUp

Rounding 6.0349 to two decimals is just not 6.04 hence, no, there is no such function.
Round up will round anything up. Hence, 6.0000000001 will also become 7 if you round to 0 decimals.

Related

VB.net Round off Decimal number to the nearest integer

I'm new to VB.net coding i would like to know how to round of a decimal number to the nearest integer
Eg. X= (5-2/2) = 1.5
but I need only as 1.
Thank you.
You can use the integer division operator if you just want to discard any remainder:
Dim resultValue As Integer = (5-2) \ 2
Note that this is one of the differences between VB.NET and C#, in C# the normal division operator will always apply integer division, so discard the remainder.
You have other options:
resultValue = CInt(Math.Floor((5-2) / 2))
resultValue = CInt(Math.Round((5-2) / 2, MidpointRounding.ToZero))
Try this:
Math.Round( (5-2)/2, 0)
..and look into the options for the overload with the MidpointRounding param, which you can set to influence rounding when the result ends with .5. Here are some of the available options:
Math.Round((5 - 2) / 2, MidpointRounding.AwayFromZero)
Math.Round((5 - 2) / 2, MidpointRounding.ToEven)
Check the documentation (or trial & error) to see which best suits your needs.
Or if you always want either the integer below or the integer above, then also check out Math.Floor and Math.Ceiling functions.
I think you can use the floor function. For example, double floor(double x);, the floor function returns the largest integer that is smaller than or equal to x.

Rounding a variable to an integer

I have a calculation like this: 3 * 12300 / 160. The result is: 230.625. But I just want the integer part, 230.
In C, this can be done using something like this: int MyVar = (int)3*12300/160;
Is there a way in VBA (With MS-Access) for force the result to be an integer?
You can round down using the Int or Fix functions.
Since you know the result you want is a whole number, you should store the result in a variable of type Long (or Integer if you're absolutely certain it will always be smaller than 32768).
Dim l As Long
l = Int(3 / 160 * 12300) ' <~~~~ Yes, I switched the numbers around on purpose!*
MsgBox "l = " & l
* Why did I switch the numbers around? Because the expression 3 * 12300 / 160 will throw an error in VBA. Read here why: Overflow when multiplying Integers and assigning to Long

get decimal part of number in MS Access

How do you access the decimal part of a number in MS Access? More specifically I want only the component after the decimal point, but not including the decimal point. This must also work for all whole numbers. I've seen this answered for other SQL engines, but they don't work in Access. I can't be much more specific than this because of the sensitive nature of what I'm actually working on.
For example given the following numbers the input is on the left and the output is on the right. Output can be either text or a number.
Source Correct Incorrect1 Incorrect2
10.0 0 0.0 .0
3.14159 14159 0.14159 .14159
45.65 65 0.65 .65
173.0 0 0.0 .0
143.15 15 0.15 .15
If I was using C# the following code would give me what I want:
private string getDecimalComponent(double input)
{
String strInput = input.ToString();
if (strInput.Contains('.'))
{
return strInput.Split('.')[1];
}
else
{
return "0";
}
}
Subtract the integer portion of the value.
Example:
4.25 - Int(4.25) = 0.25
Or, as a sample SQL expression:
SELECT
[myDecimalNumber],
[myDecimalNumber] - Int([myDecimalNumber]) as [rightOfDecimal]
FROM tableA
Something like:
SELECT 3.14%1 AS mycolumn from mytable
Depends on the circumstance. If this is, for instance, in a textbox, you can use InStr to find the decimal, and then use the Mid() function to get the number after it. If it's part of an arithmetic equation, then I would use the Int() function and subtract one number from the other to get the difference.
If you can elaborate on how it's being used, and in what context, I can edit my answer to give you more specifics.
EDIT: After more info came to light, try this:
Public Function GetParts(Temp1 as Double)
Temp2 = Int(Temp1)
Temp3 = Mid(Temp1, InStr(Temp1, ".") + 1)
MsgBox Temp2
MsgBox Temp3
End Function
A stable solution producing String containing decimal places from Double.
SELECT DecimalPlaces(MyColumn) FROM MyTable
where the above user-defined function contains the following code:
Function DecimalPlaces(ByVal value As Double) As String
Dim intPartLen As String
intPartLen = Len(CStr(CInt(Abs(value))))
If Len(CStr(Abs(value))) > intPartLen Then
DecimalPlaces = Mid(CStr(Abs(value)), intPartLen + 2)
Else
DecimalPlaces = "0"
End If
End Function
It avoids common mistakes, so it is
locale-independent - works with any decimal separator (it only assumes it is a single character)
preserves precision - avoids subtraction, takes the result only from string representation
Note: those Abs() calls are really required (hint: -0.1)

ceil() not working as I expected

I'm trying to divide one number by another and then immediately ceil() the result. These would normally be variables, but for simplicity let's stick with constants.
If I try any of the following, I get 3 when I want to get 4.
double num = ceil(25/8); // 3
float num = ceil(25/8); // 3
int num = ceil(25/8); // 3
I've read through a few threads on here (tried the nextafter() suggestion from this thread) as well as other sites and I don't understand what's going on. I've checked and my variables are the numbers I expect them to be and I've in fact tried the above, using constants, and am still getting unexpected results.
Thanks in advance for the help. I'm sure it's something simple that I'm missing but I'm at a loss at this point.
This is because you are doing integer arithmetic. The value is 3 before you are calling ceil, because 25 and 8 are both integers. 25/8 is calculated first using integer arithmetic, evaluating to 3.
Try:
double value = ceil(25.0/8);
This will ensure the compiler treats the constant 25.0 as a floating point number.
You can also use an explicit cast to achieve the same result:
double value = ceil(((double)25)/8);
This is because the expressions are evaluated before being passed as an argument to the ceil function. You need to cast one of them to a double first so the result will be a decimal that will be passed to ceil.
double num = ceil((double)25/8);

Syntax for rounding up in VB.NET

What is the syntax to round up a decimal leaving two digits after the decimal point?
Example: 2.566666 -> 2.57
If you want regular rounding, you can just use the Math.Round method. If you specifially want to round upwards, you use the Math.Ceiling method:
Dim d As Decimal = 2.566666
Dim r As Decimal = Math.Ceiling(d * 100D) / 100D
Here is how I do it:
Private Function RoundUp(value As Double, decimals As Integer) As Double
Return Math.Ceiling(value * (10 ^ decimals)) / (10 ^ decimals)
End Function
Math.Round is what you're looking for. If you're new to rounding in .NET - you should also look up the difference between AwayFromZero and ToEven rounding. The default of ToEven can sometime take people by surprise.
dim result = Math.Round(2.56666666, 2)
You can use System.Math, specifically Math.Round(), like this:
Math.Round(2.566666, 2)
Math.Round(), as suggested by others, is probably what you want. But the text of your question specifically asked how to "roundup"[sic]. If you always need to round up, regarless of actual value (ie: 2.561111 would still go to 2.57), you can do this:
Math.Ceiling(d * 100)/100D
The basic function for rounding up is Math.Ceiling(d), but the asker specifically wanted to round up after the second decimal place. This would be Math.Ceiling(d * 100) / 100. For example, it may multiply 46.5671 by 100 to get 4656.71, then rounds up to get 4657, then divides by 100 to shift the decimal back 2 places to get 46.57.
I used this way:
Math.Round(d + 0.49D, 2)
Math.Ceiling((14.512555) * 100) / 100
Dot net will give you 14.52. So, you can use above syntax to round the number up for 2 decimal numbers.
I do not understand why people are recommending the incorrect code below:
Dim r As Decimal = Math.Ceiling(d * 100D) / 100D
The correct code to round up should look like this:
Dim r As Double = Math.Ceiling(d)
Math.Ceiling works with data type Double (not Decimal).
The * 100D / 100D is incorrect will break your results for larger numbers.
Math.Ceiling documentation is found here: http://msdn.microsoft.com/en-us/library/zx4t0t48.aspx