Round to increments of 2.5? - vb.net

I need to round a value up to the nearest multiple of 2.5.
For example:
6 --> 7.5
7.6 --> 10
etc.
This seems like the best way to do this?
Function RoundToIncrement(ByVal originalNumber As Decimal, ByVal increment As Decimal) As Decimal
Dim num = Math.Round(originalNumber / increment, MidpointRounding.AwayFromZero) * increment
If originalNumber Mod increment <> 0 And num < originalNumber Then
num += increment
End If
Return num
End Function

Divide the number by 2.5, round up to the nearest integer, then multiply the result by 2.5.
You're close.
Function RoundToIncrement(ByVal orignialNumber As Decimal, ByVal increment As Decimal) As Decimal
Return Math.Ceiling( orignialNumber / increment ) * increment
End Function
Math.Ceiling will always round non-integers up, so you don't need the post-adjustment.

Divide the number by 2.5. Round to nearest 1. Multiply by 2.5.
Beware of cumulative errors, and you're all set.
-Adam

/*
This will round up (Math.Ceiling) or down (Math.Floor) based on the midpoint of the increment.
The other examples use Math.Ceiling and therefore always round up.
Assume the increment is 2.5 in this example and the number is 6.13
*/
var halfOfIncrement = Increment / 2; // 2.5 / 2 = 1.25
var floorResult = Math.Floor(originalNumber / Increment); //Math.Floor(6.13 / 2.5) = Math.Floor(2.452) = 2
var roundingThreshold = (floorResult * Increment) + halfOfIncrement; //(2 * 2.5) = 5 + 1.25 = 6.25
if (originalNumber >= roundingThreshold) //6.13 >= 6.25 == false therefore take Math.Floor(6.13/2.5) = Math.Floor(2.452) = 2 * 2.5 = 5
result = Math.Ceiling(originalNumber / Increment) * Increment;
else
result = Math.Floor(originalNumber / Increment) * Increment;

Related

Truncate decimals in string VB

I need only 4 decimals in a string.
Dim testString As String = "78.568134"
I want to truncate testString to = "78.5681"
Try the following methods based on your needs and modifications;
Try method 1)
Function TrimDigits(val As Double, Optional numdig As Integer = 2) As Double
Try
Return Fix(val * 10 ^ numdig) / 10 ^ numdig
Catch ex As Exception
Return 0
End Try
End Function
Try method 2)
truncatedNumber = Fix ( originalNumber * 100 ) / 100 'Truncate to 2 decimals.
truncatedNumber = Fix ( originalNumber * 1000 ) / 1000 'Truncate to 3 decimals.
truncatedNumber = Fix ( originalNumber * 10000 ) / 10000 'Truncate to 4 decimals.
Aside note
Fix() returns the integer portion of a number.
Example 01: Truncate 3.1415 to 2 decimals.
3.1415 x 100 equals 314.15
Fix(314.15) returns 314
314 / 100 equals 3.14
Example 02: Truncate 3.1415 to 3 decimals.
3.1415 x 1000 equals 3141.5
Fix(3141.5) returns 3141
3141 / 1000 equals 3.141
Int does not truncate negative numbers correctly. Int converts -8.4 to -9, and Fix converts -8.4 to -8. So Fix is the way to go
Code to find the index of the decimal point and truncate the string if there are more than 4 characters after it.
Dim stringLen As Integer = testString.Length
Dim decimalOffset As Integer = testString.IndexOf(".", 0)
If decimalOffset >= 0 Then
If stringLen > decimalOffset + 5 Then testString = testString.SubString(0, decimalOffset + 5)
End If
This is if you are only working with Strings. If you are working with Doubles there are other ways to do this.

MS Excel. VBA function returns #value

It would be nice if someone could explain what causes function above return #value error.
Public Function papild(x)
Dim Sum As Double, A As Double, pi As Double,
Sum = 0.5 - (x - pi / 4)
A = -(x - pi / 4)
pi = Application.WorksheetFunction.pi()
Dim k As Integer, i As Integer
k = 2
i = 0
Do While Abs(A) > 0.0001
A = -A * 4 * A * A / (k + i) * (k + i + 1)
Sum = Sum + A
k = k + 1
i = i + 1
Loop
paplid = Sum
End Function
Function takes x value from MS Excel cell and it's equal = -1.5708 (=-PI()/2 #Formula Bar)
In lines 3 and 4 you work with variable pi before setting it in line 5...
Could there be some brackets missing in your formula. It basically says:
A = -4A^3 * (k+i+1)/(k+1)
This obviously drifts to +/- infinite so your loop cannot end.
Also there is a comma too much in the second line and a spelling error in the last line (paplid instead of papild).
Have you tried debugging the code?
When I run the code I get an overflow error # the 6th iteration of the while loop starting with x = -1.5708. Number gets to large to fit inside variable
.Other than that there are some minor things:
missing As Double
Public Function papild(x) As Double
and unnecessary comma at the end
Dim Sum As Double, A As Double, pi As Double,

Rounding up to nearest higher integer in VBA

I'm trying to calculate how many layers a commodity will be stacked in. I have a variable quantity (iQty), a given width for the loadbed (dRTW), a width per unit for the commodity (dWidth) and a quantity per layer (iLayerQty).
The quantity per layer is calculated as iLayerQty = Int(dRTW/dWidth)
Now I need to divide the total quantity by the quantity per layer and round up. In an Excel formula it would be easy, but I'm trying to avoid WorksheetFunction calls to minimise A1/R1C1 confusion. At the moment I'm approximating it with this:
(Number of layers) = ((Int(iQty / iLayerQty) + 1)
And that works fine most of the time - except when the numbers give an integer (a cargo width of 0.5 m, for instance, fitting onto a 2.5 m rolltrailer). In those instances, of course, adding the one ruins the result.
Is there any handy way of tweaking that formula to get a better upward rounding?
I don't see any reason to avoid WorksheetFunction; I don't see any confusion here.
Number_of_layers = WorksheetFunction.RoundUp(iQty / iLayerQty, 0)
You could also roll your own function:
Function RoundUp(ByVal Value As Double)
If Int(Value) = Value Then
RoundUp = Value
Else
RoundUp = Int(Value) + 1
End If
End Function
Call it like this:
Number_of_layers = RoundUp(iQty / iLayerQty)
If using a WorksheetFunction object to access a ROUNDUP or CEILING function is off the table then the same can be accomplished with some maths.
Number of layers = Int(iQty / iLayerQty) - CBool(Int(iQty / iLayerQty) <> Round(iQty / iLayerQty, 14))
A VBA True is the equivalent of (-1) when used mathematically. The VBA Round is there to avoid 15 digit floating point errors.
I use -int(-x) to get the ceiling.
?-int(-1.1) ' get ceil(1.1)
2
?-int(1.1) ' get ceil(-1.1)
-1
?-int(-5) ' get ceil(5)
5
These are the functions I put together for this purpose.
Function RoundUp(ByVal value As Double) as Integer
Dim intVal As Integer
Dim delta As Double
intVal = CInt(value)
delta = intVal - value
If delta < 0 Then
RoundUp = intVal + 1
Else
RoundUp = intVal
End If
End Function
Function RoundDown(ByVal value As Double) as Integer
Dim intVal As Integer
Dim delta As Double
intVal = CInt(value)
delta = intVal - value
If delta <= 0 Then
RoundDown = intVal
ElseIf delta > 0 Then
RoundDown = intVal - 1
End If
End Function
This is my Ceiling in VBA.
Function Ceiling(ByVal Number As Double, ByVal Significance As Double) As Double
Dim intVal As Long
Dim delta As Double
Dim RoundValue As Double
Dim PreReturn As Double
If Significance = 0 Then
RoundValue = 1
Else
RoundValue = 1 / Significance
End If
Number = Number * RoundValue
intVal = CLng(Number)
delta = intVal - Number
If delta < 0 Then
PreReturn = intVal + 1
Else
PreReturn = intVal
End If
Ceiling = PreReturn / RoundValue
End Function

Transform decimal is removing my zeros

how can I make sure that the results dont remove the last 0 for example, this produces "1.454" instead of "1.4540"
Dim test1 As Decimal = 14540
Debug.Print(TransformDecimal(test1, 1))
Private Shared Function TransformDecimal(value As Decimal, numberOfPlaces As Integer) As Decimal
Dim min = CDec(Math.Pow(10, numberOfPlaces - 1))
Dim max = CDec(Math.Pow(10, numberOfPlaces))
If (value >= max) Then
While value >= max
value /= 10
End While
ElseIf (value < min) Then
While value < min
value *= 10
End While
End If
Return value
End Function
You really must put Option Explicit On.
When you don't and you have, for example, this code Dim x As Decimal = 1.0 you are creating a Double and then converting it to Decimal. With Option Strict On this code won't compile.
When you write this code Dim x As Decimal = 1.0d you are immediately creating a Decimal- and that preserves the decimal places.
So, if you now write your method like this:
Private Shared Function TransformDecimal(value As Decimal, numberOfPlaces As Integer) As Decimal
Dim min = CDec(Math.Pow(10, numberOfPlaces - 1))
Dim max = CDec(Math.Pow(10, numberOfPlaces))
If (value >= max) Then
While value >= max
Dim bits = Decimal.GetBits(value)
bits(3) = ((bits(3) \ 65536) + 1) * 65536
value = New Decimal(bits)
End While
ElseIf (value < min) Then
While value < min
Dim bits = Decimal.GetBits(value)
bits(3) = ((bits(3) \ 65536) - 1) * 65536
value = New Decimal(bits)
End While
End If
Return value
End Function
And call it like this:
Dim test1 As Decimal = 14540d
Debug.Print(TransformDecimal(test1, 1).ToString())
You'll find that you get the result you want:
1.4540
The crux of this code is the lines bits(3) = ((bits(3) \ 65536) + 1) * 65536 & bits(3) = ((bits(3) \ 65536) - 1) * 65536 which shift the exponent to change the decimal by multiples of 10.

Round an integer number in VB.NET

How could I round an integer number based on the last digit of the number?
For example:
Dim x As Integer = 12
Dim y As Integer = 139
Dim z As Integer = 2322
The result should be:
x = 20
y = 140
z = 2330
Use:
Math.Ceiling(value / 10) * 10
reference: http://msdn.microsoft.com/en-us/library/zx4t0t48.aspx#Y0
x = Math.Ceiling(x / 10.0) * 10
Module Module1
Public Function RoundUp(ByVal val As Double, ByVal pos As Integer) As Double
Dim base10 As Double = System.Math.Pow(10, pos) 'pos +: right from float point, -: left from float point.
If val > 0 Then
Return System.Math.Ceiling(val * base10) / base10
Else
Return System.Math.Floor(val * base10) / base10
End If
End Function
Sub Main()
System.Console.WriteLine(RoundUp(12, -1)) '20
System.Console.WriteLine(RoundUp(139, -1)) '140
System.Console.WriteLine(RoundUp(2322, -1)) '2330
System.Console.WriteLine(RoundUp(3.1415926, 3)) '3.142
System.Console.ReadKey()
End Sub
End Module
As an alternative, doing this subtraction is a fast way:
x = value + ((2200000000 - value) % 10)
Considering that value is int (2200000000 > int.MaxValue):