I have made a program to solve a quadratic equation, and it works fine except for when the part in the square root is less than 0. When this happens I want it to display that there are no roots. This is the code I am using at the moment.
SquareRoot = System.Math.Sqrt((B ^ 2) - (4 * A * C))
If SquareRoot < 0 Then
lblRoot1.Text = "No Root"
lblRoot2.Text = "No Root"
However despite this if I run the program where this is the case, it crashes. How do I fix this? (Please can you keep the answer as simple as possible as I am still a beginner)
Your problem is that you are checking the wrong thing for negative value. The square root of a negative number is imaginary, and that is the error you get when your code crashes. Instead, move the check to the determinant, like so (this is pseudo-code only):
IF (B * B) - (4 * A * C) < 0
lblRoot1.Text = "No Root"
lblRoot2.Text = "No Root"
ELSE
SquareRoot = System.Math.Sqrt((B * B) - (4 * A * C))
For convenience you may want to create a variable to hold the determinant calculation like so:
Dim D As Integer = (B * B) - (4 * A * C) 'Use appropriate datatype instead of Integer
Why not simply use temporary variable:
Dim value = (B ^ 2) - (4 * A * C)
If value < 0 Then
' error handling
Else
Dim SquareRoot = System.Math.Sqrt(value)
End If
When you debug your program, you should see that the exception occurs in line
SquareRoot = System.Math.Sqrt((B ^ 2) - (4 * A * C))
The reason is that you are not allowed to use a negative input value to Sqrt (there is no "negative" square root, cannot be mathematically) so you need to do something like this:
Input = (B ^ 2) - (4 * A * C)
If Input >= 0 Then
SquareRoot = System.Math.Sqrt(Input)
Else
lblRoot1.Text = "No Root"
lblRoot2.Text = "No Root"
Related
I need to solve the following Least Squares Problem where A and B and X are all matrices:
cvx_begin quiet;
variable X(len_x) nonnegative;
minimize ( norm(X * A - B , 2));
subject to
X >= 0;
for i=1: size(X,2)
for j= i + 1: size(X,2)
transpose(X(:,i)) * X(:,j) <= epsilon
end
end
cvx_end
I choose CVX, but it doesn't require me to transform the problem into standard form. But with CVX, I get the following error:
Error using cvx/quad_form (line 230)
The second argument must be positive or negative semidefinite.
Error in * (line 261)
[ z2, success ] = quad_form( xx, P, Q, R );
Error in sanaz_opt (line 28)
transpose(X(:,i)) * X(:,j) <= 0.1
I'm wondering how I can solve this problem? I'm trying to use Gurobi or least squares function in Matlab, but it seems they can't handle the transpose(X(:,i)) * X(:,j) constraint.
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.
I'm having a problem with some vba code.
I have a if statement that doesn't treat the same content equally.
e.g: 0,1 equals 0,1, but a re-run 0,1 does not equal 0,1
(this values are shown by MVBA)
The code is long so before posting it i would like to know if it's possible to see the machine perspective in a if statement (hex, ascii...). This because, although the debug is telling me they are the same (through msgbox, vartype, etc), the if statement is not activated.
pseudo code:
x = 0,0000001 * 1*10^6 (which equals 0,1)
y = 0,0001 * 1*10^3 (which also equals 0,1)
if statement:
x doesn't enter
y does
end if
This is because the floating-point implementation may not be able to represent those number accurately due to the fact that they are encoded in a base 2 representation.
If you want to compare them, I would suggest using Cdec (wich converts to Decimal, a VBA custom base 10 floating-point)
Debug.Print (0.0000001 * 1 * 10 ^ 6) = (0.0001 * 1 * 10 ^ 3) ' False
Debug.Print CDec(0.0000001 * 1 * 10 ^ 6) = CDec(0.0001 * 1 * 10 ^ 3) ' True
While they both display 0.1, in fact 0.0000001 * 1 * 10 ^ 6 flaoting-point value is 0x3FB9999999999999 whereas 0.0001 * 1 * 10 ^ 3 returns 0x3FB999999999999A.
I'd recommend reading What Every Computer Scientist Should Know About Floating-Point Arithmetic
I keep getting this compile error based on the code below and I cannot figure it out for the life of me. Can you guys see what the problem is? It highlights the "p" when I go back to debug.
Thanks,
R
Function EuroBin(S, K, T, rF, sigma, n, PutCall As String)
dt = T / n: u = Exp(sigma * Sqr(dt))
d = 1 / u: p = (Exp(rF * dt) - d) / (u - d)
EuroBin = 0
For i = 0 To n
Select Case PutCall
Case "Call":
EuroBin = WorksheetFunction.Combin(n, i) * EuroBin + p^(i) * (1 - p) ^ (n - i) * WorksheetFunction.Max(S * u^(i) * d^(n - i) - K, 0)
Case "Put":
EuroBin = WorksheetFunction.Combin(n, i) * EuroBin + p^(i) * (1 - p) ^ (n - i) * WorksheetFunction.Max(K - S * u^(i) * d^(n - i), 0)
End Select
Next i
EuroBin = Exp(-rF * T) * EuroBin
End Function
For exponentiation, use
WorksheetFunction.Power(b, e)
instead of b^e, which seems to not work in VBA!
I'm saying that based on the test Debug.Print 2^2, which returns 2 2; Debug.Print WorksheetFunction.Power(2, 2) returns 4.
Exponentiation works like you expect when you use the caret ^ in 32-bit Excel VBA. It fails to work as expected only in 64-bit Excel VBA.
In 64-bit Excel VBA, the caret is the type declaration character for the LongLong variable type. So when you enter a number followed by a caret or a variable name followed by the caret, VBA assumes you are talking about a LongLong constant or variable. Having made that assumption, it then tries to parse the expression and will give you either a run-time error or an unexpected result.
If you surround your constant or variable in parentheses like (a)^b or (2)^3, you may then use the caret to perform exponentiation in 64-bit Excel VBA. That is my recommended practice as it works as expected in 32-bit Excel VBA, too.
You may also notice that doubling the caret appears to exponentiate correctly--but that is only true for whole numbers. The first caret converts your whole number into a LongLong, while the second one performs the exponentiation. But you can't count on this behavior in general, because 2.3^^3 will raise a run-time error (because 2.3 can't be a LongLong). And if your code is used in both 32-bit and 64-bit Excel, doubling the caret will produce a run-time error in 32-bit Excel. For these reasons, I recommend against the practice of doubling the caret.
I am in the process of converting Mathcad code into VBA and am trying to figure out how to replicate the While loop, which asks the program to run the loop while TGuess < 0. At the end of the loop is an if statement to break the loop if sGuess>1/1.4 (I would attach a picture, but my reputation does not allow me to).
I have written this code in VBA, but am wondering if including the sGuess variable in the original While statement is correct, or if it could influence the output of the loop:
While TGuess < 0 And sGuess <= 1 / 1.4
kterm = (kj ^ (1 / 6)) / 26 'k term in the numerator of depth equation
epw = 3 / 5
FDepth = ((kterm * RainInt * L * CF) / sGuess ^ 0.5) ^ epw
tflow = UW_Wat * g * sGuess * FDepth 'Calc Flow Shear Stress
pflow = 7.853 * UW_Wat * (tflow / UW_Wat) ^ (3 / 2)
TGuess = pflow - pcrit 'Recalc TGuess as E-P
sGuess = sGuess + SlopeInc 'Calc new stable slope
Wend
Any input would be appreciated.
To mitigate your concern, it might be better to replace the while...wend loop with a Do While ... Loop block. You can then put your break condition where you'd have it in the corresponding Mathcad code by using something along the lines of
If sGuess > 1/1.4 Then
Exit Do
End If