VBA - showing wrong results - vba

I have come across a issue while working in VBA . I'm supposed to write program that is Numerical integration of trapeze method (I'm not sure if It is how it's called in English) of function 100*x^99 lower limit = 0 upper limit = 1 . Cells (j,5) contains numbers (10,30,100,300,1000,3000,10000) - amount of point splits . Code seems to work but given wrong results , for amount of splits it should be around
10 - 5.000295129200607
30 - 1.786588019299606
100 - 1.0812206997600746
300 - 1.0091505687770146
1000 - 1.0008248693208752
3000 - 1.0000916650530287
10000 - 1.000008249986933
Function F(x)
F = 100 * (x ^ 99)
End Function
Sub calka()
Dim n As Single
Dim xp As Single
Dim dx As Single
Dim xk As Single
Dim ip As Single
Dim pole As Single
xp = 0
xk = 1
For j = 5 To 11
n = Cells(j, 5)
dx = (xk - xp) / n
pole = 0
For i = 1 To n - 1
pole = pole + F(xp + i * dx)
Next i
pole = pole + ((F(xp) + F(xk)) / 2)
pole = pole * dx
Worksheets("Arkusz1").Cells(j, 7) = pole
Next j
End Sub
I tried to implement same code in java and c++ and it worked flawlessly but VBA always gives me wrong results , I'm not sure if it's rounds at some point and I can disable in settings or my code is just not written right .
Apologies for low clarity It's hard for me to translate mathematic to English.

Use Doubles rather than Singles
http://www.techrepublic.com/article/comparing-double-vs-single-data-types-in-vb6/

Related

Unexpected Rounding Error

can someone please explain the following to me?
Sub TestCalc()
Dim Z As Double
Dim Y As Double
Dim X As Integer
Dim W As Double
Dim V As Double
X = 44 / 14 ' returns 3
Z = (0.14 * 14) ' returns 1.96
Y = ((44 / 14) - (44 \ 14)) * 14 ' returns 2 SHOULD RETURN 1.96
W = (44 / 14) - X ' returns 0.142857142857143
V = W * 14 ' returns 2 SHOULD RETURN 1.96
End Sub
1.96 is the value that I would expect to get from the code. However, I only get this value when I use hard coded values. If I work with variables it rounds it up and returns the value 2 (Y or V). I'm need to understand why, as 1.96 is that value that I expect to be returned. I need to ensure that it performs this calculation correctly to ensure that my math formula functions properly in my main procedure
Your expectations are incorrect.
0.14 * 14 = 1.96; however, W is 0.142857142857143 - that value * 14 = 2.
I am guessing that there are some unseen conditions determining if the numbers you are entering are being calculated as integers or doubles. What happens when you type out Y as
Y = ((44.0 / 14.0) - (44.0 \ 14.0)) * 14.0
or however you can specify doubles in Visual Basic.
Also the bottom of this article mentions a mode that warns you when unsafe conversions take place which might help track it down.
https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/operators-and-expressions/arithmetic-operators

Converting an equation to code

I have an equation that can be used to find the gun elevation for artillery, using the range, muzzle velocity and change in altitude in a game called Arma 3. The equation looks like this:
With g being the acceleration due to gravity (9.80665), V being the muzzle velocity, X being the range and Y being the change in altitude (called DAlt in my code).
I'm trying to convert it to a line of code so that I can make a program to calculate the elevation based on given coordinates. However I'm having trouble with it. I currently have this:
If rdoLow.Checked = True Then
Elevation = Math.Atan(((Velocity ^ 2) - (Math.Sqrt((Velocity ^ 4) - (G) * (G * (Range ^ 2) + (2 * DAlt * (Velocity ^ 2)))))) / G * Range)
Else
Elevation = Math.Atan(((Velocity ^ 2) + (Math.Sqrt((Velocity ^ 4) - (G) * (G * (Range ^ 2) + 2 * DAlt * (Velocity ^ 2))))) / G * Range)
End If
Which isn't particularly nice looking but as far as I can tell, it should work. However when I put in the values that the video I got the equation from used, I got a different answer. So there must be something wrong with my equation.
I've tried breaking it in to various parts as separate variables and calculating them, then using those variables in the overall equation, and that still didn't work and gave me an answer that was wrong in another way.
So I'm currently at a loss on how to fix it, starting to wonder if the way that vb handles long equations is different or something.
Any help is much appreciated.
You haven't given any sample data, so I can't verify that this gives the correct answer, but the last part of your equation is missing some parentheses.
Elevation = Math.Atan(((Velocity ^ 2) + Math.Sqrt((Velocity ^ 4) - (G * ((G * (Range ^ 2)) + (2 * DAlt * (Velocity ^ 2)))))) / (G * Range))
Note the parenthesis around the last G * Range.
Multiplication and division have equal precedence, so they are evaluated from left-to-right. See Operator Precedence in Visual Basic.
You were dividing everything by G, then multiplying the result by Range, whereas you needed to multiply G by Range, then divide everything by the result of that.
You can see the difference in this simple example:
Console.WriteLine(3 / 4 * 5) ' Prints 3.75
Console.WriteLine(3 / (4 * 5)) ' Prints 0.15
Out of curiosity I tried the problem. In order to have test data I found this web site, Range Tables For Mortars. I tested with the '82mm Mortar - Far' that has an initial velocity of 200 m/s. One problem I had, and don't know if I fixed it correctly, was that the first part of the equation was returning negative numbers... I also solved for the ±. To test I created a form with a button to perform the calculation, a textbox to enter the distance, and two labels to show the angles. This is what I came up with.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'A - launch angle
'Target
' r - range
' y - altitude
'g - gravity 9.80665 m/s^2
'v - launch speed e.g. 50 m/s
'
'
'Formula
'from - https://en.wikipedia.org/wiki/Trajectory_of_a_projectile#Angle_required_to_hit_coordinate_.28x.2Cy.29
'in parts
'parts - px
' p1 = sqrt( v^4 - g * (g * r^2 + 2 * y * v^2) )
' p2 = v^2 ± p1 note plus / minus
' p3 = p2 / g * r
'
' A = arctan(p3)
Dim Ap, Am, r, y As Double
Dim g As Double = 9.80665
Dim v As Double
Dim p1, p2p, p2m, p3p, p3m As Double
If Not Double.TryParse(TextBox1.Text, r) Then Exit Sub
y = 0
v = 200 '82mm Mortar - Far velocity
p1 = v ^ 4 - g * (g * r ^ 2 + 2 * y * v ^ 2)
If p1 < 0 Then
Debug.WriteLine(p1)
p1 = Math.Abs(p1) 'square root does not like negative numbers
End If
p1 = Math.Sqrt(p1)
'plus / minus
p2p = v ^ 2 + p1
p2m = v ^ 2 - p1
p3p = p2p / (g * r)
p3m = p2m / (g * r)
Const radiansToDegrees As Double = 180 / Math.PI
Ap = Math.Atan(p3p) * radiansToDegrees
Am = Math.Atan(p3m) * radiansToDegrees
Label1.Text = Ap.ToString("n3")
Label2.Text = Am.ToString("n3")
End Sub
Using the web site to verify the calculations the code seem correct.
Writing long formulas in a bunch of nested parentheses serves no purpose, unless you are going for confusion.

VB.net: How to have an unknown algebra for a equation

I am creating a calculator to cover the tax of an input.
How do I have an unknown integer "m" as something like an algebra for my equation?
b = m - tm
"b" is money after tax. "m" is money before being taxed and "t" is Tax Rate in decimal
-
Example 1 - Money to cover tax [To find unknown variable 'm'] [t=0.06/6%]
100000000 = m - 0.06m ~ Plug-in all available numbers
100000000 = 0.94m ~ Subtraction
106382978 = m ~ Division
-
What is the code so that I can make m a unknown variable to be solved? VB.net Please help!
From what I understand, you want to solve for m. This means given a value for b and t, you want to find m.
Algebraically:
m = b/ (1-t)
The above equation is what you need to put in your program. Be aware that t=1 will cause an error, so make an 'IF' statement before you execute the equation.
It based on previous solution and it's pretty dirty
Dim restCash = 4500
Dim taxRate = 0.1 ' e.x 10%
Dim initialCash = 0 ' That's what we looking for
If (taxRate = 1) Then ' It means that taxRate = 100%
MsgBox("Tax rate cannot be 100%")
Return
Else
initialCash = restCash / (1 - taxRate)
End If

VB challenge/ help MONTE CARLO INTEGRATION

Im trying to create Monte-Carlo simulation that can be used to derive estimates for integration problems (summing up the area under
a curve). Have no idea what to do now and i am stuck
"to solve this problem we generate a number (say n) of random number pairs for x and y between 0 and 1, for each pair we see if the point (x,y) falls above or below the line. We count the number of times this happens (say c). The area under the curve is computed as c/n"
Really confused please help thank you
Function MonteCarlo()
Dim a As Integer
Dim b As Integer
Dim x As Double
Dim func As Double
Dim total As Double
Dim result As Double
Dim j As Integer
Dim N As Integer
Console.WriteLine("Enter a")
a = Console.ReadLine()
Console.WriteLine("Enter b")
b = Console.ReadLine()
Console.WriteLine("Enter n")
N = Console.ReadLine()
For j = 1 To N
'Generate a new number between a and b
x = (b - a) * Rnd()
'Evaluate function at new number
func = (x ^ 2) + (2 * x) + 1
'Add to previous value
total = total + func
Next j
result = (total / N) * (b - a)
Console.WriteLine(result)
Console.ReadLine()
Return result
End Function
You are using the rejection method for MC area under the curve.
Do this:
Divide the range of x into, say, 100 equally-spaced, non-overlapping bins.
For your function y = f(x) = (x ^ 2) + (2 * x) + 1, generate e.g. 10,000 values of y for 10,000 values of x = (b - a) * Rnd().
Count the number of y-values in each bin, and divide by 10,000 to get a "bin probability." --> p(x).
Next, the proper way to randomly simulate your function is to use the rejection method, which goes as follows:
4a. Draw a random x-value using x = (b - a) * Rnd()
4b. Draw a random uniform U(0,1). If U(0,1) is less than p(x) add a count to the bin.
4c. Continue steps 4a-4b 10000 times.
You will now be able to simulate your y=f(x) function using the rejection method.
Overall, you need to master these approaches before you do what you want since it sounds like you have little experience in bin counts, simulation, etc. Area under the curve is always one using this approach, so just be creative for integrating using MC.
Look at some good textbooks on MC integration.

I need some help on designing a program that will perform a minimization using VBA Excel

How do I use Excel VBA to find the minimum value of an equation?
For example, if I have the equation y = 2x^2 + 14, and I want to make a loop that will slowly increase/decrease the value of x until it can find the smallest value possible for y, and then let me know what the corresponding value of x is, how would I go about doing that?
Is there a method that would work for much more complicated equations?
Thank you for your help!
Edit: more details
I'm trying to design a program that will find a certain constant needed to graph a nuclear decay. This constant is a part of an equation that gets me a calculated decay. I'm comparing this calculated decay against a measured decay. However, the constant changes very slightly as the decay happens, which means I have to use something called a residual-square to find the best constant to use that will fit the entire decay best to make my calculated decay as accurate as possible.
It works by doing (Measured Decay - Calculated Decay) ^2
You do that for the decay at several times, and add them all up. What I need my program to do is to slowly increase and decrease this constant until I can find a minimum value for the value I get when I add up the residual-squared results for all the times using this decay. The residual-squared that has the smallest value has the value of the constant that I want.
I already drafted a program that does all the calculations and such. I'm just not sure how to find this minimum value. I'm sure if a method works for something like y = x^2 + 1, I can adapt it to work for my needs.
Test the output while looping to look for the smallest output result.
Here's an Example:
Sub FormulaLoop()
Dim x As Double
Dim y As Double
Dim yBest As Double
x = 1
y = (x ^ 2) + 14
yBest = y
For x = 2 To 100
y = (x ^ 2) + 14
If y < yBest Then
yBest = y
End If
Next x
MsgBox "The smallest output of y was: " & yBest
End Sub
If you want to loop through all the possibilities of two variables that make up x then I'd recommend looping in this format:
Sub FormulaLoop_v2()
Dim MeasuredDecay As Double
Dim CalculatedDecay As Double
Dim y As Double
Dim yBest As Double
MeasuredDecay = 1
CalculatedDecay = 1
y = ((MeasuredDecay - CalculatedDecay) ^ 2) + 14
yBest = y
For MeasuredDecay = 2 To 100
For CalculatedDecay = 2 To 100
y = ((MeasuredDecay - CalculatedDecay) ^ 2) + 14
If y < yBest Then
yBest = y
End If
Next CalculatedDecay
Next MeasuredDecay
MsgBox "The smallest output of y was: " & yBest
End Sub