I have to format some decimal values into specific logic. I would like to round input values always into either to 5 or 9. How can i accomplish that easiest way, is there any function already? Below find examples what i am trying to reach. On the left are some input values and on the right are output i would like to achieve. Is there any easy way to do so?
Input Formatted
------ ----------
614,46 = 615,00
614,57 = 615,00
615,01 = 619,00
616,57 = 619,00
91,11 = 95,00
96,11 = 99,00
89,25 = 95,00
There is nothing build in for your case but you can easily implement it by your own:
Public Sub Main()
Console.WriteLine("{0:N2}", myFlor(614.46))
Console.WriteLine("{0:N2}", myFlor(614.57))
Console.WriteLine("{0:N2}", myFlor(615.01))
Console.WriteLine("{0:N2}", myFlor(616.57))
Console.WriteLine("{0:N2}", myFlor(91.11 ))
Console.WriteLine("{0:N2}", myFlor(96.11 ))
Console.WriteLine("{0:N2}", myFlor(89.25 ))
End Sub
Function myFlor(ByVal value As Double) As Double
Dim base as Integer
base = Math.Truncate(value / 10) *10
If value - base > 9
' Handle 9.01 -9.99 case
Return base + 15
ElseIf value - base > 5
Return base + 9
Else
Return base + 5
End If
End Function
If I understand correctly you need to use Ceiling method to returns the smallest integer greater than or equal to the specified number and then round this integer to the nearest 5 or 9.
I don't think you can obtain this behaviour without writing your own function:
Private Function intRoundTo5Or9(ByVal dblNumber As Double) As Integer
Dim intLastDigit As Integer = CInt(Math.Ceiling(dblNumber).ToString().Substring(Math.Ceiling(dblNumber).ToString().Length - 1, 1))
If intLastDigit <= 5 Then
Return Math.Ceiling(dblNumber) + 5 - intLastDigit
Else
Return Math.Ceiling(dblNumber) + 9 - intLastDigit
End If
End Function
Related
I am trying to make a quick sort however i am having trouble with a stack overflow exception in VB.net.
The sort works correctly when x = 3, intermittently when x = 5 and on one occasion sorted half of the list when x = 10.
Please advise, thanks
Dim x As Integer = 10
Dim numArrray(x - 1) As Integer
For i = 0 To x - 1
Randomize()
numArrray(i) = CInt(Rnd() * 9)
Next
Quicksort(numArrray, 0, numArrray.Length - 1)
For i = 0 To x - 1
Console.Write(numArrray(i))
Next
Console.ReadLine()
End Sub
Sub Quicksort(ByVal array() As Integer, ByVal min As Integer, ByVal max As Integer)
Dim pivot As Integer
If min < max Then
pivot = partition(array, min, max)
Quicksort(array, min, pivot - 1)
Quicksort(array, pivot + 1, max)
End If
End Sub
Function partition(ByVal array() As Integer, ByVal min As Integer, ByVal max As Integer) As Integer
Dim pivot As Integer = array(max)
Dim count As Integer = min - 1
Dim placeholder As Integer
For i = min To max - 1
If array(i) < pivot Then
count += 1
placeholder = array(count)
array(count) = array(i)
array(i) = placeholder
End If
Next
If array(max) < array(count + 1) Then
placeholder = array(count + 1)
array(count + 1) = array(max)
array(max) = placeholder
End If
Return count
End Function
Since its a stack overflow it will be in the nested calls to Quicksort, looking at partition I think you have a bounds error, as per this version of the algorithm en.wikipedia.org/wiki/Quicksort you should return count + 1 from partition, on your current implementation count can start below min and stay that way which would be an infinite regression as your nested call would have the same inputs (ie if you return count = min - 1 then you do a recursive call back to Quicksort(array, pivot + 1, max) == Quicksort(array, min, max)
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
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.
I would like to make CPU to calculate declared result from the given numbers that are also declared.
So far:
Dim ArrayOperators() As String = {"+", "-", "*", "/", "(", ")"}
Dim GlavniBroj As Integer = GBRnb() 'Number between 1 and 999 that CPU needs to get from the numbers given below:
Dim OsnovniBrojevi() As Integer = {OBRnb(), OBRnb(), OBRnb(), OBRnb()} '4 numbers from 1 to 9
Dim SrednjiBroj As Integer = SBRnb() '1 number, 10, 15 or 20 chosen randomly
Dim KrajnjiBroj As Integer = KBRnb() '25, 50, 75 or 100 are chosen randomly
Private Function GBRnb()
Randomize()
Dim value As Integer = CInt(Int((999 * Rnd()) + 1))
Return value
End Function
Private Function OBRnb()
Dim value As Integer = CInt(Int((9 * Rnd()) + 1))
Return value
End Function
Private Function SBRnb()
Dim value As Integer = CInt(Int((3 * Rnd()) + 1))
If value = 1 Then
Return 10
ElseIf value = 2 Then
Return 15
ElseIf value = 3 Then
Return 20
End If
Return 0
End Function
Private Function KBRnb()
Dim value As Integer = CInt(Int((4 * Rnd()) + 1))
If value = 1 Then
Return 25
ElseIf value = 2 Then
Return 50
ElseIf value = 3 Then
Return 75
ElseIf value = 4 Then
Return 100
End If
Return 0
End Function
Is there any way to make a program to calculate GlavniBroj(that is GBRnb declared) with the help of the other numbers (also without repeating), and with help of the given operators? Result should be displayed in the textbox, in a form of the whole procedure of how computer got that calculation with that numbers and operators. I tried to make it work by coding operations one by one, but that's a lot of writing... I'm not looking exactly for the code answer, but mainly for the coding algorithm. Any idea? Thanks! :)
I don't know why this code doesn't work ..i wanna just convert text to number .. It doesn't give me any error but it doesn't work
Public Function ConvertCOMPLEXITYToNumber(ByVal chain As String) As Integer
Select Case chain
Case "1 - Très difficile"
ConvertCOMPLEXITYTToNumber = 1
Case "2 - Difficile"
ConvertCOMPLEXITYTToNumber = 2
Case "3 - Modérée"
ConvertCOMPLEXITYTToNumber = 3
Case "4 - Facile"
ConvertCOMPLEXITYTToNumber = 4
Case Else
ConvertCOMPLEXITYTToNumber = 0
End Select
Exit Function
End Function
That may be because you may have unwanted leading or trailing spaces which fails the comparison. Also you do not need Exit Function at the end of the code. It will exit any ways :)
Try this
Public Function ConvertCOMPLEXITYToNumber(ByVal chain As String) As Integer
Dim Num As Integer
Select Case Trim(chain)
Case "1 - Très difficile": Num = 1
Case "2 - Difficile": Num = 2
Case "3 - Modérée": Num = 3
Case "4 - Facile": Num = 4
Case Else: Num = 0
End Select
ConvertCOMPLEXITYToNumber = Num
End Function
If IsNumeric(Left(Trim(chain),1)) Then
ConvertCOMPLEXITYToNumber = Left(Trim(chain),1)
Else
ConvertCOMPLEXITYToNumber = 0
End If
Here, my approach for you:
Public Function ConvertCOMPLEXITYToNumber(ByVal chain As String) As Integer
'Get the first character
chain = Left(Trim(chain), 1)
'If frist character is numeric
If IsNumeric(chain) Then
'If first number is less than 5, return value
If chain < 5 Then
ConvertCOMPLEXITYToNumber = CInt(chain)
End If
End If
End Function