I have the overloaded function
Vector3D^ Vector3D:: operator + (Vector3D^ toAdd) // Adding 2 vectors
{
Vector3D^ temp = gcnew Vector3D();
temp->x = x + toAdd->x;
temp->y = y + toAdd->y;
temp->z = z + toAdd->z;
return temp;
}
But whenever I call
double x1 = Convert::ToDouble(txtAx->Text);
double x2 = Convert::ToDouble(txtBx->Text);
double y1 = Convert::ToDouble(txtBx->Text);
double y2 = Convert::ToDouble(txtBx->Text);
double z1 = Convert::ToDouble(txtBx->Text);
double z2 = Convert::ToDouble(txtBx->Text);
Vector3D vectorA(x1, y1, z1);
Vector3D vectorB(x2, y2, z2);
Vector3D temp;
temp = vectorA + vectorB;
I get a no operator matches these functions errors. Every website suggests doing it this way.
Related
I have written a macro which computes x and y values. I am having trouble trying to write those values to cells on Excel.
I get #VALUE error when I try to display the values on the cell.
I have added my code below. Any suggestion about what is wrong with the code will be really helpful and appreciated?
Thanks in advance!
'Compute Points
Function ComputePoints(x1, y1, x2, y2, distance) As Double
'Calculate slope m
Dim m As Double
m = (y2 - y1) / (x2 - x1)
'Calculate intercept
Dim Intercept As Double
Intercept = y1 - m * x1
'Calculate x for distFinal
Dim message As String
Dim a As Double
Dim b As Double
Dim c As Double
Dim root1 As Double
Dim root2 As Double
Dim det As Double
Dim det1 As Double
Dim wb As Workbook
Dim ws As Worksheet
Dim x1Rng As Range
Dim x2Rng As Range
Dim yRng As Range
a = (m ^ 2 + 1)
b = 2 * (Intercept * m - m * y2 - x2)
c = x2 ^ 2 + (Intercept - y2) ^ 2 - distance ^ 2
det = ((b ^ 2) - (4 * a * c))
det1 = Sqr(det)
message = "There is no solution to your equation"
If det < 0 Then
MsgBox message, vbOKOnly, "Error"
Else
root1 = Round((-b + det1) / (2 * a), 2)
root2 = Round((-b - det1) / (2 * a), 2)
End If
'Compute y
Dim y As Double
y = m * root2 + Intercept
' Trying to set cell values to root1, root2, y
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Sheet9")
Set x1Rng = ws.Range("N2")
Set x2Rng = ws.Range("O2")
Set yRng = ws.Range("P2")
x1Rng.Value2 = root1
x2Rng.Value2 = root2
yRng.Value2 = y
ComputePoints = y
End Function
I modified your code slightly to get values directly in excel cells. You need to select 3 horizontal cells, press F2 / =, enter your formula and then press Ctrl Shift Enter to make it an array formula.
This will give you the three output values in the cells.
Function ComputePoints(x1, y1, x2, y2, distance)
Dim results(3) As Variant ' #nightcrawler23
'Calculate slope m
Dim m As Double
m = (y2 - y1) / (x2 - x1)
'Calculate intercept
Dim Intercept As Double
Intercept = y1 - m * x1
'Calculate x for distFinal
Dim message As String
Dim a As Double
Dim b As Double
Dim c As Double
Dim root1 As Double
Dim root2 As Double
Dim det As Double
Dim det1 As Double
a = (m ^ 2 + 1)
b = 2 * (Intercept * m - m * y2 - x2)
c = x2 ^ 2 + (Intercept - y2) ^ 2 - distance ^ 2
det = ((b ^ 2) - (4 * a * c))
det1 = Sqr(det)
message = "There is no solution to your equation"
If det < 0 Then
MsgBox message, vbOKOnly, "Error"
Else
root1 = Round((-b + det1) / (2 * a), 2)
root2 = Round((-b - det1) / (2 * a), 2)
End If
'Compute y
Dim y As Double
y = m * root2 + Intercept
results(1) = root1 ' #nightcrawler23
results(2) = root2 ' #nightcrawler23
results(3) = y ' #nightcrawler23
ComputePoints = results ' #nightcrawler23
End Function
You need to add some code to output error message, when no roots are found
I'm trying to create a a program that will draw hypotrochoids (spirograph). The program below compiles fine. But when I run it I only get a portion of the drawing.. I'm not sure what I'm doing wrong. I'm fairly new to VB.. Any help is appreciated. Thanks.
Here is the screenshot http://imgur.com/a/KxFWk
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
Dim x As Integer
Dim y As Integer
Dim p As Integer
Dim x1 As Integer
Dim y1 As Integer
Dim x2 As Integer
Dim y2 As Integer
x = 75
y = 15
p = 15
x1 = (x + y) * Math.Cos(0) + p * Math.Cos(0)
y1 = (x + y) * Math.Sin(0) + p * Math.Sin(0)
For t = 0 To 500 Step 0.1
x2 = (x + y) * Math.Cos(t) + p * Math.Cos((x + y) * t / y)
y2 = (x + y) * Math.Sin(t) + p * Math.Sin((x + y) * t / y)
e.Graphics.DrawLine(Pens.Blue, x1, y1, x2, y2)
x1 = x2
y1 = y2
Next
End Sub
End Class
The results of the Sin and Cos calculations result in negative numbers where the parameter is greater than 90 for cos and greater than 180 for sin.
To see the whole image, you need to change the offset for x2 and y2 - see the code below. Alter the number 200 in each of the four lines to a value appropriate for your picturebox
x1 = 200 + CInt((x + y) * Math.Cos(0) + p * Math.Cos(0))
y1 = 200 + CInt((x + y) * Math.Sin(0) + p * Math.Sin(0))
For t As Double = 0 To 500 Step 0.1
x2 = 200 + CInt((x + y) * Math.Cos(t) + p * Math.Cos((x + y) * t / y))
y2 = 200 + CInt((x + y) * Math.Sin(t) + p * Math.Sin((x + y) * t / y))
e.Graphics.DrawLine(Pens.Blue, x1, y1, x2, y2)
x1 = x2
y1 = y2
Next
I am using VBA for the first time. I started with a very basic code using Runga Kutta Method. I am not able to run it. Can I know where I am going wrong? Can you also post some solutions for this type of differential equation solvers?
Option Explicit
Dim K1 As Double
Dim K2 As Double
Dim K3 As Double
Dim K4 As Double
Dim y As Double
Dim x As Double
Dim dx As Double
Dim x0 As Integer
Dim y0 As Integer
Function f(x, y) As Double
f = 0.5 * x - 0.5 * y
End Function
Sub RK(x, y, dx)
Dim i As Integer
Dim ynew As Double
dx = 0.5
x0 = 0
y0 = 1
K1 = dx * f(x, y)
K2 = dx * f(x + dx / 2, y + K1 / 2)
K3 = dx * f(x + dx / 2, y + K2 / 2)
K4 = dx * f(x + dx, y + K3)
RK = y + ((K1 + 2 * (K2 + K3 + K4)) / 6)
For i = 0 To 6
ynew = RK(x, y, dx)
x = x + dx
y = ynew
Next i
For j = 1 To 6
Call RK(x, y, dx, ynew)
ActiveCell.Offset(i - 1, 1).Value = x
ActiveCell.Offset(i - 1, 2).Value = y
x = x + dx
y = ynew
Next
End Sub
You need to execute the RK procedure and give it the starting values of x, y and dx.
To do this from within the VBE (Visual Basic Editor) open the Immediate window. If it's not visible press Ctrl+G and it should appear at the bottom of the VBE.
In the Immediate window type something like RK 1, 3, 2 and the results will appear in the two columns to the right of the active cell and take up 6 rows.
If you want the procedure to execute on the press of a button, or when a value is updated you'll need to add an extra bit of code for that.
Edit:
Just noticed these lines - RK = y + ((K1 + 2 * (K2 + K3 + K4)) / 6) and ynew = RK(x, y, dx).
The RK procedure won't return a value and you can't set it as a value either.
This link may help explain it: http://what-when-how.com/excel-vba/vba-sub-and-function-procedures/
I've written a function to find out the area and centroid of a polygon (based on this ref: http://en.wikipedia.org/wiki/Centroid )
However, I am very new to F# and I don't know how to convert this function from VB.NET to F# (VS2010). If anyone could please help me, that would be really appreciated (Assuming that in F# I already have a type called Point2D, and the input of F# function is a list of point2D) . My first attempt is below the VB code. But I don't like my version, since it has to calculate Cx, Cy ,and A serparately - which is not a true reflection of my VB code counterpart
Private Function Find_Centroid_And_Area(ByVal List As List(Of Point2D)) As AreaCentroid
Dim result As New AreaCentroid()
Try
Dim Qx As Double = 0
Dim Qy As Double = 0
Dim A As Double = 0
Dim Cx As Single = 0
Dim Cy As Single = 0
Dim P1 As Point2D = Nothing
Dim P2 As Point2D = Nothing
For i As Integer = 0 To List.Count - 1
P1 = List(i)
Select Case i
Case List.Count - 1
P2 = List(0)
Case Else
P2 = List(i + 1)
End Select
Dim Dx As Double = P2.X - P1.X
Dim Dy As Double = P2.Y - P1.Y
Dim Lx As Double = P1.X + (Dx / 3)
Dim Ly As Double = P1.Y + (Dy / 3)
A += (Dx * (P1.Y + P2.Y)) / 2
Qx += (Dx * ((P1.Y ^ 2) + (Dy * Ly))) / 2
Qy -= (Dy * ((P1.X ^ 2) + (Dx * Lx))) / 2
Next
Cx = CSng(Qy / A)
Cy = CSng(Qx / A)
Dim Centroid As New Point2D(Cx, Cy)
Dim Area As Double = System.Math.Abs(A)
result.Area = Area
result.Centroid = Centroid
Catch ex As Exception
End Try
Return result
End Function
and here is my attempt :
type Point2D =
struct
val X:float
val Y:float
new(x:float, y:float) = {X=x; Y=y}
end
let PolygonCentroidArea (points: Point2D list) =
let length = List.length points
match length < 3 with
| true ->
let A = 0.0
let Cx = (points |> List.map (fun p -> p.X) |> List.average)
let Cy = (points |> List.map (fun p -> p.Y) |> List.average)
(A, Point2D(Cx,Cy)) // returned value
| false ->
let TakeFirst2ItemInList (pointList : Point2D list) =
let p1 = List.head pointList
let tail = List.tail pointList
let p2 = List.head tail
let newList = List.tail tail
(p1,p2,newList)
let rec Area pointList =
match (List.length pointList) with
| 0 -> 0.0
| _ ->
let (p1,p2,newList) = TakeFirst2ItemInList pointList
(p1.X+p2.Y-p2.X*p1.Y) + Area newList
let rec Cx pointList =
match (List.length pointList) with
| 0 -> 0.0
| _ ->
let (p1,p2,newList) = TakeFirst2ItemInList pointList
(p1.X+p2.X)*(p1.X*p2.Y-p2.X*p1.Y) + Cx newList
let rec Cy pointList =
match (List.length pointList) with
| 0 -> 0.0
| _ ->
let (p1,p2,newList) = TakeFirst2ItemInList pointList
(p1.Y+p2.Y)*(p1.Y*p2.X-p2.Y*p1.X) + Cy newList
let FinalArea = 1.0/2.0 * abs(Area points)
let FinalCx = 1.0/(6.0*FinalArea) * Cx points
let FinalCy = 1.0/(6.0*FinalArea) * Cy points
(FinalArea, Point2D(FinalCx,FinalCy))
I did translations from VB in the past, my advice is have a first working version with the same structure as the original VB Code:
type Point2D =
struct
val X:float
val Y:float
new(x:float, y:float) = {X =x; Y=y}
end
let rec PolygonCentroidArea (points: Point2D list) =
let mutable Qx = 0.
let mutable Qy = 0.
let mutable A = 0.
let length = List.length points
for i = 0 to length-1 do
let P1 = points.[i]
let P2 =
if i = length - 1 then points.[0]
else points.[i + 1]
let Dx = P2.X - P1.X
let Dy = P2.Y - P1.Y
let Lx = P1.X + (Dx / 3.)
let Ly = P1.Y + (Dy / 3.)
A <- A + (Dx * (P1.Y + P2.Y)) / 2.
Qx <- Qx + (Dx * (pown P1.Y 2 + Dy * Ly)) / 2.
Qy <- Qy - ((Dy * (pown P1.X 2 + Dx * Lx))) / 2.
let Cx = Qy / A
let Cy = Qx / A
(abs A, Point2D(Cx, Cy))
Once here we can refactor the function to a more F#-ish solution. The mutables and the loops may be converted to folds. In this case we use two consecutive elements from the list, so it sounds that we may use Seq.pairwise somewhere, also we can rearrange the calculation as you did in your answer.
Here's my solution:
let PolygonCentroidArea (points: Point2D list) =
let f (a, qx, qy) (p1: Point2D,p2: Point2D) =
let area = a + p1.X * p2.Y - p1.Y * p2.X
let centX = qx + (p1.X + p2.X) * (p1.X + p2.Y - p1.Y * p2.X)
let centY = qy + (p1.Y + p2.Y) * (p1.X + p2.Y - p1.Y * p2.X)
area, centX, centY
let a, qx, qy = Seq.fold f (0., 0., 0.) (Seq.pairwise (points # [points.Head]))
abs a / 2., Point2D(qx / 6. / abs a, qy / 6. / abs a)
Based on people's answers and ideas, and for the balance between readability and the conciseness of the code - here I am editing my original solution - which may potentially help others looking for the solutions of the same issue:
type Point2D =
struct
val X:float
val Y:float
new(x,y) = {X=x;Y=y}
end
let PolygonCentroidArea (points: Point2D list) =
let Elemement ((p1:Point2D), (p2:Point2D)) =
let cross = p1.X * p2.Y - p1.Y * p2.X
let A = cross
let Cx = cross * (p1.X+p2.X)
let Cy = cross * (p1.Y+p2.Y)
(A, Cx,Cy)
let SumElement (a1,cx1,cy1) (a2,cx2,cy2) = (a1+a2,cx1+cx2,cy1+cy2)
let (A ,Cx, Cy) =
points
|> Seq.pairwise
|> Seq.map Elemement
|> Seq.fold SumElement (0.,0.,0.)
(abs A/2. ,Cx/(6.*abs A), Cy/(6.*abs A))
let points = [Point2D(1.,0.); Point2D(5.,0.); Point2D(5.,2.); Point2D(1.,2.); Point2D(1.,0.)]
let test = PolygonCentroidArea points
//val test : float * float * float = (8.0, 1.5, 0.5)
While the gist of the other answers is perfectly acceptable, I'm slightly worried by the erroneous result. Let me suggest to introduce a helper type which can perform the summation, allowing us to replace the unintuitive fold by the more natural sum.
type Sum3 = internal Sum3 of float * float * float with
static member Zero = Sum3(0., 0., 0.)
static member (+) (Sum3(a, b, c), Sum3(x, y, z)) = Sum3(a + x, b + y, c + z)
let polygonCentroidArea points =
let (Sum3(a, cx, cy)) =
points # [List.head points]
|> Seq.pairwise
|> Seq.sumBy (fun ((x0, y0), (x1, y1)) ->
let z = x0 * y1 - x1 * y0 in Sum3(z, (x0 + x1) * z, (y0 + y1) * z) )
let a = abs a / 2. in a, cx / 6. / a, cy / 6. / a
polygonCentroidArea[0., 0.; 4., 0.; 4., 2.; 0., 2.]
// val it : float * float * float = (8.0, 2.0, 1.0)
I am getting a compile error in Excel VBA which says Expected Sub, Function or Property. The function I am using is given below which is trying to copy the rate function in Excel.
Thanks for your help.
Function rate_m(nper As Double, pmt As Double, pv As Double, fv As Double, types As Double, guess As Double) As Variant
Dim y, y0, y1, x0, x1, f, i As Double
Dim FINANCIAL_MAX_ITERATIONS As Double
Dim FINANCIAL_PRECISION As Double
If IsNull(guess) Then guess = 0.01
If IsNull(fv) Then fv = 0
If IsNull(types) Then types = 0
FINANCIAL_MAX_ITERATIONS = 128 'Bet accuracy with 128
FINANCIAL_PRECISION = 0.0000001 '1.0e-8
y , y0, y1, x0, x1, f, i = 0
rate_m = guess
If Abs(rate_m) < FINANCIAL_PRECISION Then
y = pv * (1 + nper * rate_m) + pmt * (1 + rate_m * types) * nper + fv
Else
f = Exp(nper * Log(1 + rate_m))
y = pv * f + pmt * (1 / rate_m + types) * (f - 1) + fv
y0 = pv + pmt * nper + fv
y1 = pv * f + pmt * (1 / rate_m + types) * (f - 1) + fv
End If
'find root by Newton secant method
i , x0 = 0
x1 = rate_m
While Abs(y0 - y1) > FINANCIAL_PRECISION & i < FINANCIAL_MAX_ITERATIONS
rate_m = (y1 * x0 - y0 * x1) / (y1 - y0)
x0 = x1
x1 = rate_m
If Abs(rate_m) < FINANCIAL_PRECISION Then
y = pv * (1 + nper * rate_m) + pmt * (1 + rate_m * types) * nper + fv
Else
f = Exp(nper * Log(1 + rate_m))
y = pv * f + pmt * (1 / rate_m + types) * (f - 1) + fv
End If
y0 = y1
y1 = y
i = i + 1
Wend
End Function
A couple things...
First, you have to assign each variable individually...like this:
y = 0
y0 = 0
y1 = 0
x0 = 0
x1 = 0
f = 0
i = 0
Second, you probably want to DIM your variables all as Double. Unfortunately, this line:
Dim y, y0, y1, x0, x1, f, i As Double
Only declares i as a Double, all the others will be a Variant. You need to declare each one individually, like this:
Dim y As Double
Dim y0 As Double
Dim y1 As Double
Dim x0 As Double
Dim x1 As Double
Dim f As Double
Dim i As Double
Every IF ends with a End If (unless in a single line) and While...loop. You might want to take a look at VBA's syntax:
http://msdn.microsoft.com/en-us/library/office/ee814737(v=office.14).aspx
EDIT: You have to declare variable individually, instead of:
y , y0, y1, x0, x1, f, i = 0
you could do:
y = 0
y0 = 0
y1 = 0
x0 = 0
x1 = 0
f = 0
i = 0