Getting NaN for a double datatype - vb.net

I am trying to run some mathematical formula which has large values, so I am using the Double datatype. But still I am getting the answer as NaN if I input large values. So how can I solve this?
For example, if I pass Varx=3 and countx=1230 I get the result as NaN.
Public Function EulerForPro(ByVal Varx As Integer, ByVal Countx As Integer) As Double
Dim Result1 As Double = 1
Dim Result2 As Double = Varx
Dim Result As Double = 0
For i = 1 To Countx
Result1 = Result1 + (Math.Pow(-1, i) * Math.Pow(Varx, (2 * i)) / factx(2 * i))
Next
For i = 1 To Countx
Result2 = Result2 + (Math.Pow(-1, i) * Math.Pow(Varx, ((2 * i) + 1)) / factx((2 * i) + 1))
Next
Result = Result1 + Result2
Label2.Text = Result1
Label3.Text = Result2
Label4.Text = Result
End Function

Use the logarithm of the results. It is standard practice for large numbers.
So instead of multiplying a*b (which causes overflow), use
Y = log(a) + log(b)

You could try using the Decimal data type instead. It can hold an integer value of approximately 7,9 x 10^28 (the exact number is 2^96 - 1, since it can use 96 bits of its 128 for storing the integer part of a value). However, it's a complex data type and you should carefully consider how to use it in your code. Not all implicit conversions work, especially when using Double.
See MSDN on decimal for exact specifications of Decimal.

Related

Label a set of objects with (A->Z,AA->ZZ, AAA->ZZZ) in VBA

I have a set which has an unknown number of objects. I want to associate a label to each one of these objects. Instead of labeling each object with a number I want to label them with letters.
For example the first object would be labeled A the second B and so on.
When I get to Z, the next object would be labeled AA
AZ? then BA, BB, BC.
ZZ? then AAA, AAB, AAC and so on.
I'm working using Mapbasic (similar to VBA), but I can't seem to wrap my head around a dynamic solution. My solution assumes that there will be a max number of objects that the set may or may not exceed.
label = pos1 & pos2
Once pos2 reaches ASCII "Z" then pos1 will be "A" and pos2 will be "A". However, if there is another object after "ZZ" this will fail.
How do I overcome this static solution?
Basically what I needed was a Base 26 Counter. The function takes a parameter like "A" or "AAA" and determines the next letter in the sequence.
Function IncrementAlpha(ByVal alpha As String) As String
Dim N As Integer
Dim num As Integer
Dim str As String
Do While Len(alpha)
num = num * 26 + (Asc(alpha) - Asc("A") + 1)
alpha = Mid$(alpha, 2,1)
Loop
N = num + 1
Do While N > 0
str = Chr$(Asc("A") + (N - 1) Mod 26) & str
N = (N - 1) \ 26
Loop
IncrementAlpha = str
End Function
If we need to convert numbers to a "letter format" where:
1 = A
26 = Z
27 = AA
702 = ZZ
703 = AAA etc
...and it needs to be in Excel VBA, then we're in luck. Excel's columns are "numbered" the same way!
Function numToLetters(num As Integer) As String
numToLetters = Split(Cells(1, num).Address(, 0), "$")(0)
End Function
Pass this function a number between 1 and 16384 and it will return a string between A and XFD.
Edit:
I guess I misread; you're not using Excel. If you're using VBA you should still be able to do this will the help of an reference to an Excel Object Library.
This should get you going in terms of the logic. Haven't tested it completely, but you should be able to work from here.
Public Function GenerateLabel(ByVal Number As Long) As String
Const TOKENS As String = "ZABCDEFGHIJKLMNOPQRSTUVWXY"
Dim i As Long
Dim j As Long
Dim Prev As String
j = 1
Prev = ""
Do While Number > 0
i = (Number Mod 26) + 1
GenerateLabel = Prev & Mid(TOKENS, i, 1)
Number = Number - 26
If j > 0 Then Prev = Mid(TOKENS, j + 1, 1)
j = j + Abs(Number Mod 26 = 0)
Loop
End Function

Vb.Net Value show zero for next loop ctype

After run the program I show value of Power1 is zero, why?
Here codes;
Dim Guc1....Guc59 as decimal
Guc1=Val(TextBox5.Text)*Val(Textbox98.Text)
.
.
.
Guc59=Val(TextBox42.Text)*Val(Textbox12.Text)
For i = 1 To 59 Step 2
Dim txt As TextBox = CType(TabControlPanel1.Controls("TextBoxX" & i), TextBox)
Dim guc As Decimal = CType(("Guc".ToString & i), Decimal)
Hız1 = Val(txt.Text) * RollinRadius * 3.14 * 3.6 / (Val(TextBox1.Text) * Val(TextBox33.Text) * 30)
Power1 = guc * 3.14 / (30 * 1000) *2 *3)
ListBox2.Items.Add(Power1)
Next
Power1 is zero because guc will currently always be zero. You cannot access variables by their names like you're trying to do. "Guc" & i will just result in a normal string, which it cannot convert since Guc is not numerical. The only way to access variables dynamically by their name is to use Reflection.
But the best way to do what you're trying to achieve is to use a List(Of T) or an Array:
Dim Guc As Decimal = New Decimal(59 - 1) {} '59 - 1 = 59 items.
...
Dim gucx As Decimal = Guc(i - 1)
...
Power1 = gucx * 3.14 / (30 * 1000) * 2 * 3

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.

Automatic Calculation with given numbers

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! :)