Extracting Terms from simple linear equation

W

William Benson

I have a basic linear equation of this form (Note, parentheses and grouped
terms will not matter):

-25 + 3*X + 15*Y - 4*X^2 + 8*X^2*Y^-2

Note: never this form -25 + 3*X + 15*Y - 4*X^2 (1 - 2 Y^-2)

Can someone please help me build a parsing routine to isolate terms, and
whether they are preceded by a + or a -. I am using two separate arrays
because I later have to work with each term to calculate a derivative.
Negative exponent must be treated differently than a minus sign. ArrTerms
and ArrOps() should look like this at the end of the above exercise, and be
generalizable:

i ArrTerms( i ) ArrOps( i )
1 25 -
2 3*X +
3 15*Y +
4 4*X^2 -
5 8*X^2*Y^-2 +

I'd be very appreciative for help with the required (generalizable) routine.
If I can clarify something, please e-mail me (w b e n s o n 1 @ n y c a p .
r r . c o m) or post here.

Thanks!
 
T

Tom Ogilvy

some pseudo code. (since it uses split, it won't work in xl97) Assumes
spaces before and after the operators as shown.

dim ArrTerms() as String, ArrOps() as String
redim ArrTerms(0 to 20)
redim ArrOps(0 to 20)
Dim i as long, j as long
Dim b as Boolean
i = 0, j = 1
sSTr = -25 + 3*X + 15*Y - 4*X^2 + 8*X^2*Y^-2
v = Split(sSTr," ")
b = True
for k = lbound(v) to ubound(v)
if b then
ArrTerms(i) = v(k)
i = i + 1
else
ArrOps(j) = v(k)
j = j + 1
end if
b = not b
Next k
Redim preserve ArrTerms(0 to i - 1)
Redim preserve ArrOps(0 to j - 1)

-25 looks like a unary operator to me. Same as your negative exponent.

If you want it to be stored as a sign, you can pass through the ArrTerms and
look for this situation and move the sign to ArrOps. Not sure how you got
your final Plus sign, but it could be added it at end.

Another approach would be to replace ^- with a unique symbol. Then loop
through the string and separate on finding a plus or minus. Then after
separated, go through and change the unique symbol to ^-.


If you just need the answer to the formula, use Replace to replace the X's
and Y's with your values for each in the string, then use Evalute. No
parsing required.
 
W

William Benson

Thanks Tom

I am sorry this changes the game for you ... but I have tried (and failed)
to remove spaces within terms while leaving them in between terms.
Therefore, an equation where you will actually be starting will look like:
sSTR = -25+3*X+15*Y-4*X^2+8*X^2*Y^-2 which will not parse with your method
per se, because you are using a space. My bad!!!! "bad OP!!!!" "bad OP!!!!!"

Here's what I think I can do, using your basic approach, pls tell me what
you think of it -- I will not ask you to actually code and test it:

(1) Change "^-" to "^^", that avoids the risk that negative exponents will
get parsed away from their term-mates

(2) Created two strings instead of just one

(3a) Use your method to split one string based first on minus sign
Discard any terms that begin with a "+"

(3b) Repeat on the other string, split based on plus sign
Discard any terms that begin with a "-"

(4) Combine the ramainders in ArrTerms [This is the dicey-est part to me]

(5) The ArrOps values we can force to "+" or "-" depending on which string
(i.e., are we in 3a or 3b).


Last: I have no control over the number of terms at this point, so I
hesitate to use the Dimming logic you used, but I have some other method
that forward advances the ubound of the arrays, so that is no problem.
 
T

Tom Ogilvy

Not sure you need to do a 3a and 3b.

Lightly tested:

Option Explicit
Sub ABCD()
Dim ArrTerms() As String, ArrOps() As String
Dim i As Long, j As Long, k As Long
Dim b As Boolean
Dim s As String, sStr As String
Dim sChr As String
Dim sStr1 As String
i = 0
j = 0

sStr = "-25+3*X+15*Y-4*X^2+8*X^2*Y^-2"
sStr1 = Application.Substitute(sStr, " ", "")
sStr1 = Application.Substitute(sStr, "^-", "^^")
s = Left(sStr1, 1)
If s <> "-" And s <> "+" Then _
sStr1 = "+" & sStr1
s = ""
For k = 1 To Len(sStr1)
sChr = Mid(sStr1, k, 1)
If sChr = "+" Or sChr = "-" Then
ReDim Preserve ArrOps(0 To j)
If k <> 1 Then
ArrOps(j) = sChr
j = j + 1
ReDim Preserve ArrTerms(0 To i)
ArrTerms(i) = Application.Substitute(s, _
"^^", "^-")
i = i + 1
s = ""
Else
ArrOps(j) = sChr
j = j + 1
End If
Else
s = s & sChr
End If
Next k
If s <> "" Then
ReDim Preserve ArrTerms(0 To i)
ArrTerms(i) = Application.Substitute(s, _
"^^", "^-")
End If
For k = 0 To UBound(ArrTerms)
Debug.Print k, ArrTerms(k), ArrOps(k)
Next
Debug.Print UBound(ArrTerms), UBound(ArrOps)
End Sub

--
Regards,
Tom Ogilvy

William Benson said:
Thanks Tom

I am sorry this changes the game for you ... but I have tried (and failed)
to remove spaces within terms while leaving them in between terms.
Therefore, an equation where you will actually be starting will look like:
sSTR = -25+3*X+15*Y-4*X^2+8*X^2*Y^-2 which will not parse with your method
per se, because you are using a space. My bad!!!! "bad OP!!!!" "bad OP!!!!!"

Here's what I think I can do, using your basic approach, pls tell me what
you think of it -- I will not ask you to actually code and test it:

(1) Change "^-" to "^^", that avoids the risk that negative exponents will
get parsed away from their term-mates

(2) Created two strings instead of just one

(3a) Use your method to split one string based first on minus sign
Discard any terms that begin with a "+"

(3b) Repeat on the other string, split based on plus sign
Discard any terms that begin with a "-"

(4) Combine the ramainders in ArrTerms [This is the dicey-est part to me]

(5) The ArrOps values we can force to "+" or "-" depending on which string
(i.e., are we in 3a or 3b).


Last: I have no control over the number of terms at this point, so I
hesitate to use the Dimming logic you used, but I have some other method
that forward advances the ubound of the arrays, so that is no problem.

Tom Ogilvy said:
some pseudo code. (since it uses split, it won't work in xl97) Assumes
spaces before and after the operators as shown.

dim ArrTerms() as String, ArrOps() as String
redim ArrTerms(0 to 20)
redim ArrOps(0 to 20)
Dim i as long, j as long
Dim b as Boolean
i = 0, j = 1
sSTr = -25 + 3*X + 15*Y - 4*X^2 + 8*X^2*Y^-2
v = Split(sSTr," ")
b = True
for k = lbound(v) to ubound(v)
if b then
ArrTerms(i) = v(k)
i = i + 1
else
ArrOps(j) = v(k)
j = j + 1
end if
b = not b
Next k
Redim preserve ArrTerms(0 to i - 1)
Redim preserve ArrOps(0 to j - 1)

-25 looks like a unary operator to me. Same as your negative exponent.

If you want it to be stored as a sign, you can pass through the ArrTerms
and
look for this situation and move the sign to ArrOps. Not sure how you got
your final Plus sign, but it could be added it at end.

Another approach would be to replace ^- with a unique symbol. Then loop
through the string and separate on finding a plus or minus. Then after
separated, go through and change the unique symbol to ^-.


If you just need the answer to the formula, use Replace to replace the X's
and Y's with your values for each in the string, then use Evalute. No
parsing required.



--
Regards,
Tom Ogilvy


and
be p
.
 
W

William Benson

Tom, this is fantastic.
Bill


PS - the upper bound of the
Tom Ogilvy said:
Not sure you need to do a 3a and 3b.

Lightly tested:

Option Explicit
Sub ABCD()
Dim ArrTerms() As String, ArrOps() As String
Dim i As Long, j As Long, k As Long
Dim b As Boolean
Dim s As String, sStr As String
Dim sChr As String
Dim sStr1 As String
i = 0
j = 0

sStr = "-25+3*X+15*Y-4*X^2+8*X^2*Y^-2"
sStr1 = Application.Substitute(sStr, " ", "")
sStr1 = Application.Substitute(sStr, "^-", "^^")
s = Left(sStr1, 1)
If s <> "-" And s <> "+" Then _
sStr1 = "+" & sStr1
s = ""
For k = 1 To Len(sStr1)
sChr = Mid(sStr1, k, 1)
If sChr = "+" Or sChr = "-" Then
ReDim Preserve ArrOps(0 To j)
If k <> 1 Then
ArrOps(j) = sChr
j = j + 1
ReDim Preserve ArrTerms(0 To i)
ArrTerms(i) = Application.Substitute(s, _
"^^", "^-")
i = i + 1
s = ""
Else
ArrOps(j) = sChr
j = j + 1
End If
Else
s = s & sChr
End If
Next k
If s <> "" Then
ReDim Preserve ArrTerms(0 To i)
ArrTerms(i) = Application.Substitute(s, _
"^^", "^-")
End If
For k = 0 To UBound(ArrTerms)
Debug.Print k, ArrTerms(k), ArrOps(k)
Next
Debug.Print UBound(ArrTerms), UBound(ArrOps)
End Sub

--
Regards,
Tom Ogilvy

William Benson said:
Thanks Tom

I am sorry this changes the game for you ... but I have tried (and
failed)
to remove spaces within terms while leaving them in between terms.
Therefore, an equation where you will actually be starting will look
like:
sSTR = -25+3*X+15*Y-4*X^2+8*X^2*Y^-2 which will not parse with your
method
per se, because you are using a space. My bad!!!! "bad OP!!!!" "bad OP!!!!!"

Here's what I think I can do, using your basic approach, pls tell me what
you think of it -- I will not ask you to actually code and test it:

(1) Change "^-" to "^^", that avoids the risk that negative exponents
will
get parsed away from their term-mates

(2) Created two strings instead of just one

(3a) Use your method to split one string based first on minus sign
Discard any terms that begin with a "+"

(3b) Repeat on the other string, split based on plus sign
Discard any terms that begin with a "-"

(4) Combine the ramainders in ArrTerms [This is the dicey-est part to me]

(5) The ArrOps values we can force to "+" or "-" depending on which
string
(i.e., are we in 3a or 3b).


Last: I have no control over the number of terms at this point, so I
hesitate to use the Dimming logic you used, but I have some other method
that forward advances the ubound of the arrays, so that is no problem.

Tom Ogilvy said:
some pseudo code. (since it uses split, it won't work in xl97) Assumes
spaces before and after the operators as shown.

dim ArrTerms() as String, ArrOps() as String
redim ArrTerms(0 to 20)
redim ArrOps(0 to 20)
Dim i as long, j as long
Dim b as Boolean
i = 0, j = 1
sSTr = -25 + 3*X + 15*Y - 4*X^2 + 8*X^2*Y^-2
v = Split(sSTr," ")
b = True
for k = lbound(v) to ubound(v)
if b then
ArrTerms(i) = v(k)
i = i + 1
else
ArrOps(j) = v(k)
j = j + 1
end if
b = not b
Next k
Redim preserve ArrTerms(0 to i - 1)
Redim preserve ArrOps(0 to j - 1)

-25 looks like a unary operator to me. Same as your negative exponent.

If you want it to be stored as a sign, you can pass through the
ArrTerms
and
look for this situation and move the sign to ArrOps. Not sure how you got
your final Plus sign, but it could be added it at end.

Another approach would be to replace ^- with a unique symbol. Then
loop
through the string and separate on finding a plus or minus. Then after
separated, go through and change the unique symbol to ^-.


If you just need the answer to the formula, use Replace to replace the X's
and Y's with your values for each in the string, then use Evalute. No
parsing required.



--
Regards,
Tom Ogilvy


I have a basic linear equation of this form (Note, parentheses and
grouped
terms will not matter):

-25 + 3*X + 15*Y - 4*X^2 + 8*X^2*Y^-2

Note: never this form -25 + 3*X + 15*Y - 4*X^2 (1 - 2 Y^-2)

Can someone please help me build a parsing routine to isolate terms, and
whether they are preceded by a + or a -. I am using two separate
arrays
because I later have to work with each term to calculate a derivative.
Negative exponent must be treated differently than a minus sign. ArrTerms
and ArrOps() should look like this at the end of the above exercise, and
be
generalizable:

i ArrTerms( i ) ArrOps( i )
1 25 -
2 3*X +
3 15*Y +
4 4*X^2 -
5 8*X^2*Y^-2 +

I'd be very appreciative for help with the required (generalizable)
routine.
If I can clarify something, please e-mail me (w b e n s o n 1 @ n y c
a p
.
r r . c o m) or post here.

Thanks!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top