A Class for recording mathematical expressions?

A Class for recording mathematical expressions?

Post by Thomas Gagn » Fri, 19 Oct 2001 00:15:20



In the system I'm working on (brilliantly inspired and sublimely implemented
in Smalltalk) I have various calculations which are the result of several
sub-calculations.  I'd like to have a class that doesn't resolve the
expressions, but instead just keeps adding them.

Let me explain a little better.

If the class were called MathExpression, I'd like to be able to:

| aCalc |

aCalc := MathExpression new: 0.15. " starts out with 0.15"
aCalc * 100.
aCalc printString. "0.15 * 100"
aCalc / 365.
aCalc printString. "(0.15 * 100) / 365"
aCalc * 60.
aCalc printString. "((0.15 * 100) / 365) * 60"
aCalc. "2.465748"

It would be a hybrid of an OrderedCollection and a Number.  It would only
resolve itself when asked to (however that would happen).  When it's the
target of a message send, it would simply store the operator and the operand.

An interesting side-affect may be to add comments to either its elements or to
Number (or Magnitude) so that I would actually know what each of the numbers
is.

aCalc := MathExpression new: (0.15 \'annual interest rate')
aCalc * 100 \'Loan Amount'.
aCalc printStringComments. "annual interest rate * Loan amount"

.. or something along those lines.  The value increases when someone asks,
"How did you get to that number???"

If I used an adding machine, I could show them the tape, but I would have to
tell them what each of the numbers are.  When some of the numbers happen to be
the same (like if someone were borrowing $365) the adding machine's tape would
look confusing without accompanying narrative.

Does something like this already exist?

--
.tom

 
 
 

A Class for recording mathematical expressions?

Post by Peter van Rooije » Fri, 19 Oct 2001 04:49:09


Hi Tom,

Quote:> In the system I'm working on (brilliantly inspired and sublimely
implemented
> in Smalltalk) I have various calculations which are the result of several
> sub-calculations.

Keep that in mind. You just gave the answers to your own questions.

Quote:> I'd like to have a class that doesn't resolve the
> expressions, but instead just keeps adding them.

> Let me explain a little better.

> If the class were called MathExpression,

Call it Calculation instead. Expression would be more suitable if it had
variables.

Quote:> I'd like to be able to:

> | aCalc |

Man, you even call the var aCalc. Where did the MathExpression come from?

Quote:> aCalc := MathExpression new: 0.15. " starts out with 0.15"
> aCalc * 100.
> aCalc printString. "0.15 * 100"
> aCalc / 365.
> aCalc printString. "(0.15 * 100) / 365"
> aCalc * 60.
> aCalc printString. "((0.15 * 100) / 365) * 60"
> aCalc. "2.465748"

That last line won't work because if you choose 'show it' or 'display it',
you will get the #printString, but anyway.

Quote:> It would be a hybrid of an OrderedCollection and a Number.

No. It would be a hybrid of Tree and Block.

Quote:> It would only
> resolve itself when asked to (however that would happen).

Send it #value to get the result of evaluating it. Optionally cache the
value.

Quote:> When it's the
> target of a message send, it would simply store the operator and the

operand.

You mean, 'a binary message send', correct?

Create and return a new Calculation and let the receiver be the left
operand.

Quote:> An interesting side-affect may be to add comments to either its elements
or to
> Number (or Magnitude) so that I would actually know what each of the
numbers
> is.

> aCalc := MathExpression new: (0.15 \'annual interest rate')
> aCalc * 100 \'Loan Amount'.
> aCalc printStringComments. "annual interest rate * Loan amount"

How about:

(Calculation with: 0.15) comment: 'annual interest rate' ;
    * 100 ; comment: 'Loan amount' ;
    printStringComments

Quote:> .. or something along those lines.  The value increases when someone asks,
> "How did you get to that number???"
> If I used an adding machine, I could show them the tape, but I would have
to
> tell them what each of the numbers are.  When some of the numbers happen
to be
> the same (like if someone were borrowing $365) the adding machine's tape
would
> look confusing without accompanying narrative.

> Does something like this already exist?

Probably. Not worth searching for, though. Less than an hour to write, and
then you'll really understand it.

Very nice idea, though. A bit like the distances framework I build for the
Ensu Test Driven Development environment demo, with which the following will
be true:

1 m = 1 m
1 m ~= 2 m
1 m + 1 m = 2 m
1 km = 1000 m
1 m printString = '1 m'
2 km printString = '2 km'
1 km + 100 m = 1100 m
(1 km + 100 m) printString = '1.1 km'
(1000 m + 100 m) printString = '1100 m'

Tom, hope my comments are of some help. Do you want to develop it
test-driven? If so, it would be nice to post your test cases and ask what
other people here come up with.

Regards,

Peter van Rooijen

 
 
 

A Class for recording mathematical expressions?

Post by H. S. Lahma » Fri, 19 Oct 2001 05:38:31


Responding to Gagne...

Quote:> If the class were called MathExpression, I'd like to be able to:

> | aCalc |

> aCalc := MathExpression new: 0.15. " starts out with 0.15"
> aCalc * 100.
> aCalc printString. "0.15 * 100"
> aCalc / 365.
> aCalc printString. "(0.15 * 100) / 365"
> aCalc * 60.
> aCalc printString. "((0.15 * 100) / 365) * 60"
> aCalc. "2.465748"

> It would be a hybrid of an OrderedCollection and a Number.  It would only
> resolve itself when asked to (however that would happen).  When it's the
> target of a message send, it would simply store the operator and the operand.

I assume using a functional programming language is not an option(?)
B-)

The obvious solution is to simply encode the operators and values into a
string as they are supplied.  That string prints intermediate values as
necessary.  When it is time to calculate, one decodes the string and
computes the results from the tokens.  Alas, this has a couple of
problems.  The decode is high overhead for the calculation and there
could be problems with precedence unless one uses RPN or explicit
parentheses.

If things are as nicely expressed as indicated (i.e., always a single
operator/value pair) I would be tempted to use a FIFO stack class.  Each
operator or value token would be added directly to the stack.  The stack
can be popped or simply read for either printing or for reasonably
efficient calculation in the right order.

Quote:> An interesting side-affect may be to add comments to either its elements or to
> Number (or Magnitude) so that I would actually know what each of the numbers
> is.

> aCalc := MathExpression new: (0.15 \'annual interest rate')
> aCalc * 100 \'Loan Amount'.
> aCalc printStringComments. "annual interest rate * Loan amount"

> .. or something along those lines.  The value increases when someone asks,
> "How did you get to that number???"

> If I used an adding machine, I could show them the tape, but I would have to
> tell them what each of the numbers are.  When some of the numbers happen to be
> the same (like if someone were borrowing $365) the adding machine's tape would
> look confusing without accompanying narrative.

The class is really solving three different problems.  The first is to
build and store an expression incrementally.  The second is to compute
the arithmetic result of that expression.  The third is to record
<readable> documentation of how that expression was formed.

This suggests that there should really be more classes with different,
more cohesive responsibilities.  Perhaps something like

                ExpressionStack
                      |
          *           |        *
Expression---------------------Token
   | 1                            |
   |                              | is-a
   | 1                            |
ExpressionParser           +------+------+
                           |      |      |
                           |      |      |
                        comment value  operator

ExpressionStack adds and stores tokens incrementally in FIFO order by
instantiating the relationship (i.e., it is probably a stack collection
class that implements the relationship for a particular Expression).
Tokens are dumb and simply record different <optimal> formats.
Expression's responsibility is to compute/store the current expression
value.  ExpressionParser lives to create the current documentation from
the expression by "walking" the Expression/Token relationship.

However, this is pretty elaborate; seven classes for what might be a
real simple process (e.g., encoding/decoding a string). That underscores
the point in my first sentence: OT really isn't very well suited for
dealing with purely algorithmic or parsing processing.

[I once did an RPN parser for boolean expressions to identify the
minimum sum-of-products and wound up with a class for each token plus
several others.  Most classes had a single distinct behavior -- very
much a functional decomposition.  Very busy class diagram and not very
good OT, but in the end the total of executable statements was
astonishingly small compared to a C implementation I had done
previously.  But I suspect an FP language implementation would have been
equally compact w/o the class definition overhead.]

OTOH, if this is a recurring problem this might be reusable as-is.  It
is also pretty robust in that it can be easily modified to do things
like: providing incremental results/documentation after every addition
rather than a single, final result/documentation; supporting operator
precedence; or adding parenthesized scoping.  And by substituting a
different Expression, ExpressionParser, and/or different Token subtypes
one can do boolean expressions or even non-arithmetic expressions.  So,
though elaborate, it has some value as a general analysis pattern.

*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman

Pathfinder Solutions  -- We Make UML Work
http://www.pathfindersol.com
(888)-OOA-PATH

 
 
 

A Class for recording mathematical expressions?

Post by Richard MacDonal » Fri, 19 Oct 2001 14:04:15



You've already received some good responses.
Yes, its possible, doable, and not hard at all.
I called my superclass Function. I subclassed
unary, binary, and n-ary. Then I subclassed
for all the operations, e.g., FunctionAdd.
You could develop a fancy token/parser,
but if you're not parsing math expression
strings, you can make it easier.

2 + 2 sends the plus message to. . .well you know
that.

x = Variable new.
x value: 2.
x = Variable new.
x value: 2.
y = Variable new.
y value: 2.
z := x + y.

answers a Function that is the adder of x and y.

As long as your receiver is a Variable and not
a Number, it all works. You reimplement the
math operations in Variable to create a Function
instance. You only have to write these "creation"
methods in the Function superclass and all subclasses
pick them up automatically. Then just send #value
to get the result. The math expression tree gets
built up automatically.

Its not the fastest thing in the world, but its cool.
Also, if you want to get derivative functions,
derivative values, integrals, etc, its *really* cool.

I have all this code but it got bottled up with a
whole bunch of other things so there may be
some untangling. Also, I archived it
a while back when I (sigh) moved to Java. I
can dig it up for you but I cannot guarantee
being punctual -- several days minimum and
perhaps 2 weeks. Call me and plee if its critical
but I agree with the other poster than its only
a few hours and probably better for you to
write it just the way you want to use it.

 
 
 

A Class for recording mathematical expressions?

Post by Hans-Martin Mosne » Fri, 19 Oct 2001 18:31:06



> In the system I'm working on (brilliantly inspired and sublimely implemented
> in Smalltalk) I have various calculations which are the result of several
> sub-calculations.  I'd like to have a class that doesn't resolve the
> expressions, but instead just keeps adding them.
...
> Does something like this already exist?

In VisualWorks 5i.4, I made a quick hack based on the Smalltalk compiler classes.
I've appended the fileout for it.
To use it, just send the message #symbolic to the first value in the calculation.
Sending the message #! creates a comment attached to the preceding literal.
For example, your first case would look like:
        0.15 symbolic * 100 / (365 !'days in year') * 60
Printing this expression results in
        0.15 * 100 / (365 !'days in year') * 60 "2.46575"
You may also send it the message #explain to see the structure and intermediate results. The result is
'       0.15
*
        100
"= 15.0"
/
        365 !''days in year''
"= 0.0410959"
*
        60
"= 2.46575"
'
Here's the fileout (hope it gets through OK)

Cheers,
Hans-Martin
--------

<?xml version="1.0"?>

<st-source>
<time-stamp>From VisualWorks?, Release 5i.4 of August 9, 2001 on October 18, 2001 at 2:23:40 am</time-stamp>
<!-- Package SymbolicValues= -->

<class>
<name>SymbolicConstant</name>
<environment>Smalltalk</environment>
<super>Kernel.LiteralNode</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>SymbolicMath</category>
<attributes>
<package>SymbolicValues</package>
</attributes>
</class>

<class>
<name>SymbolicMessage</name>
<environment>Smalltalk</environment>
<super>Kernel.SimpleMessageNode</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars></inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>SymbolicMath</category>
<attributes>
<package>SymbolicValues</package>
</attributes>
</class>

<methods>
<class-id>Core.Object</class-id> <category>symbolic</category>

<body package="SymbolicValues">! aString
        ^ self symbolic ! aString</body>

<body package="SymbolicValues">symbolic
        ^SymbolicConstant new value: self</body>
</methods>

<methods>
<class-id>Kernel.ProgramNode</class-id> <category>symbolic</category>

<body package="SymbolicValues">doesNotUnderstand: aMessage
        self isSymbolicValue ifFalse: [^super doesNotUnderstand: aMessage].
        ^SymbolicMessage new
                receiver: self
                selector: aMessage selector
                arguments: (aMessage arguments collect: [:each | each symbolic])</body>

<body package="SymbolicValues">isSymbolicValue
        ^false</body>

<body package="SymbolicValues">symbolic
        ^self</body>

<body package="SymbolicValues">inspectorActions
        "The inspector sends this message and relies on error handling to detect which objects don't implement it, instead of implementing it like this in Object..."
        ^#()</body>

<body package="SymbolicValues">explain
        | str |
        str := WriteStream on: String new.
        self printExplainedOn: str indent: 0.
        ^str contents</body>

<body package="SymbolicValues">! aString
        comment := aString</body>
</methods>

<methods>
<class-id>SymbolicConstant</class-id> <category>testing</category>

<body package="SymbolicValues">isSymbolicValue
        ^true</body>
</methods>

<methods>
<class-id>SymbolicConstant</class-id> <category>accessing</category>

<body package="SymbolicValues">precedence
        ^3</body>
</methods>

<methods>
<class-id>SymbolicConstant</class-id> <category>printing</category>

<body package="SymbolicValues">printOn: aStream
        self printOn: aStream indent: 0 precedence: 2</body>

<body package="SymbolicValues">printOn: aStream indent: indent precedence: precedence
        comment == nil ifFalse: [
                precedence &gt; 1 ifFalse: [aStream nextPut: $(]].
        super printOn: aStream indent: indent precedence: precedence.
        comment == nil ifFalse: [
                aStream nextPutAll: ' !'; print: comment.
                precedence &gt; 1 ifFalse: [aStream nextPut: $)]]</body>

<body package="SymbolicValues">printExplainedOn: aStream indent: indent
        aStream tab: indent.
        self printOn: aStream.
        aStream cr</body>
</methods>

<methods>
<class-id>SymbolicMessage</class-id> <category>testing</category>

<body package="SymbolicValues">isSymbolicValue
        ^true</body>
</methods>

<methods>
<class-id>SymbolicMessage</class-id> <category>evaluating</category>

<body package="SymbolicValues">value
        ^receiver value
                perform: selector
                withArguments: (arguments collect: [:arg | arg value])</body>
</methods>

<methods>
<class-id>SymbolicMessage</class-id> <category>printing</category>

<body package="SymbolicValues">addIndentForReceiver: aSymbolicValue
        ^(aSymbolicValue precedence &gt; self precedence or: [aSymbolicValue precedence = 3])
                ifTrue: [1]
                ifFalse: [0]</body>

<body package="SymbolicValues">printExplainedOn: aStream indent: indent
        receiver printExplainedOn: aStream indent: indent + (self addIndentForReceiver: receiver).
        selector keywords with: arguments do: [:kw :arg |
                aStream tab: indent; nextPutAll: kw; cr.
                arg printExplainedOn: aStream indent: indent+1].
        aStream tab: indent; nextPutAll: '"= '; print: self value; nextPut: $"; cr</body>

<body package="SymbolicValues">printOn: aStream
        self printOn: aStream indent: 0.
        aStream nextPutAll: ' "'; print: self value; nextPut: $"</body>
</methods>

</st-source>

 
 
 

A Class for recording mathematical expressions?

Post by Randy A. Ynchaust » Fri, 19 Oct 2001 22:09:33


Thomas Gagne,

Quote:> In the system I'm working on (brilliantly inspired and sublimely
implemented
> in Smalltalk) I have various calculations which are the result of several
> sub-calculations.  I'd like to have a class that doesn't resolve the
> expressions, but instead just keeps adding them.

Cross-reference the "Command" pattern in the "Design Patterns" book.

Regards,

Randy

 
 
 

A Class for recording mathematical expressions?

Post by Thomas Gagn » Fri, 19 Oct 2001 23:48:24


I really like your comment selector, #!.  It may not be as revealing as #comment:, but it has the aesthetic appeal I'm looking for.

Why would I need to muck with the compiler stuffs?  I could perform the operation and save the result in that node.  If I did that, I would never have to worry about
evaluating the string for a final result or for a partial result.

I'm going to have to look closey at what you did (it's hard for me to read Smalltalk inside XML so I'll be loading it later to check it out).  There's some nifty stuff
in there.

Hans-Martin Mosner wrote:
> Thomas Gagne <tga...@ix.netcom.com> wrote:
> > In the system I'm working on (brilliantly inspired and sublimely implemented
> > in Smalltalk) I have various calculations which are the result of several
> > sub-calculations.  I'd like to have a class that doesn't resolve the
> > expressions, but instead just keeps adding them.
> ...
> > Does something like this already exist?

> In VisualWorks 5i.4, I made a quick hack based on the Smalltalk compiler classes.
> I've appended the fileout for it.
> To use it, just send the message #symbolic to the first value in the calculation.
> Sending the message #! creates a comment attached to the preceding literal.
> For example, your first case would look like:
>         0.15 symbolic * 100 / (365 !'days in year') * 60
> Printing this expression results in
>         0.15 * 100 / (365 !'days in year') * 60 "2.46575"
> You may also send it the message #explain to see the structure and intermediate results. The result is
> '       0.15
> *
>         100
> "= 15.0"
> /
>         365 !''days in year''
> "= 0.0410959"
> *
>         60
> "= 2.46575"
> '
> Here's the fileout (hope it gets through OK)

> Cheers,
> Hans-Martin
> --------

> <?xml version="1.0"?>

> <st-source>
> <time-stamp>From VisualWorks?, Release 5i.4 of August 9, 2001 on October 18, 2001 at 2:23:40 am</time-stamp>
> <!-- Package SymbolicValues= -->

> <class>
> <name>SymbolicConstant</name>
> <environment>Smalltalk</environment>
> <super>Kernel.LiteralNode</super>
> <private>false</private>
> <indexed-type>none</indexed-type>
> <inst-vars></inst-vars>
> <class-inst-vars></class-inst-vars>
> <imports></imports>
> <category>SymbolicMath</category>
> <attributes>
> <package>SymbolicValues</package>
> </attributes>
> </class>

> <class>
> <name>SymbolicMessage</name>
> <environment>Smalltalk</environment>
> <super>Kernel.SimpleMessageNode</super>
> <private>false</private>
> <indexed-type>none</indexed-type>
> <inst-vars></inst-vars>
> <class-inst-vars></class-inst-vars>
> <imports></imports>
> <category>SymbolicMath</category>
> <attributes>
> <package>SymbolicValues</package>
> </attributes>
> </class>

> <methods>
> <class-id>Core.Object</class-id> <category>symbolic</category>

> <body package="SymbolicValues">! aString
>         ^ self symbolic ! aString</body>

> <body package="SymbolicValues">symbolic
>         ^SymbolicConstant new value: self</body>
> </methods>

> <methods>
> <class-id>Kernel.ProgramNode</class-id> <category>symbolic</category>

> <body package="SymbolicValues">doesNotUnderstand: aMessage
>         self isSymbolicValue ifFalse: [^super doesNotUnderstand: aMessage].
>         ^SymbolicMessage new
>                 receiver: self
>                 selector: aMessage selector
>                 arguments: (aMessage arguments collect: [:each | each symbolic])</body>

> <body package="SymbolicValues">isSymbolicValue
>         ^false</body>

> <body package="SymbolicValues">symbolic
>         ^self</body>

> <body package="SymbolicValues">inspectorActions
>         "The inspector sends this message and relies on error handling to detect which objects don't implement it, instead of implementing it like this in Object..."
>         ^#()</body>

> <body package="SymbolicValues">explain
>         | str |
>         str := WriteStream on: String new.
>         self printExplainedOn: str indent: 0.
>         ^str contents</body>

> <body package="SymbolicValues">! aString
>         comment := aString</body>
> </methods>

> <methods>
> <class-id>SymbolicConstant</class-id> <category>testing</category>

> <body package="SymbolicValues">isSymbolicValue
>         ^true</body>
> </methods>

> <methods>
> <class-id>SymbolicConstant</class-id> <category>accessing</category>

> <body package="SymbolicValues">precedence
>         ^3</body>
> </methods>

> <methods>
> <class-id>SymbolicConstant</class-id> <category>printing</category>

> <body package="SymbolicValues">printOn: aStream
>         self printOn: aStream indent: 0 precedence: 2</body>

> <body package="SymbolicValues">printOn: aStream indent: indent precedence: precedence
>         comment == nil ifFalse: [
>                 precedence &gt; 1 ifFalse: [aStream nextPut: $(]].
>         super printOn: aStream indent: indent precedence: precedence.
>         comment == nil ifFalse: [
>                 aStream nextPutAll: ' !'; print: comment.
>                 precedence &gt; 1 ifFalse: [aStream nextPut: $)]]</body>

> <body package="SymbolicValues">printExplainedOn: aStream indent: indent
>         aStream tab: indent.
>         self printOn: aStream.
>         aStream cr</body>
> </methods>

> <methods>
> <class-id>SymbolicMessage</class-id> <category>testing</category>

> <body package="SymbolicValues">isSymbolicValue
>         ^true</body>
> </methods>

> <methods>
> <class-id>SymbolicMessage</class-id> <category>evaluating</category>

> <body package="SymbolicValues">value
>         ^receiver value
>                 perform: selector
>                 withArguments: (arguments collect: [:arg | arg value])</body>
> </methods>

> <methods>
> <class-id>SymbolicMessage</class-id> <category>printing</category>

> <body package="SymbolicValues">addIndentForReceiver: aSymbolicValue
>         ^(aSymbolicValue precedence &gt; self precedence or: [aSymbolicValue precedence = 3])
>                 ifTrue: [1]
>                 ifFalse: [0]</body>

> <body package="SymbolicValues">printExplainedOn: aStream indent: indent
>         receiver printExplainedOn: aStream indent: indent + (self addIndentForReceiver: receiver).
>         selector keywords with: arguments do: [:kw :arg |
>                 aStream tab: indent; nextPutAll: kw; cr.
>                 arg printExplainedOn: aStream indent: indent+1].
>         aStream tab: indent; nextPutAll: '"= '; print: self value; nextPut: $"; cr</body>

> <body package="SymbolicValues">printOn: aStream
>         self printOn: aStream indent: 0.
>         aStream nextPutAll: ' "'; print: self value; nextPut: $"</body>
> </methods>

> </st-source>

--
.tom
 
 
 

A Class for recording mathematical expressions?

Post by Thomas Gagn » Fri, 19 Oct 2001 23:43:09



> Hi Tom,

> > In the system I'm working on (brilliantly inspired and sublimely
> implemented
> > in Smalltalk) I have various calculations which are the result of several
> > sub-calculations.

> Keep that in mind. You just gave the answers to your own questions.

> > I'd like to have a class that doesn't resolve the
> > expressions, but instead just keeps adding them.

> > Let me explain a little better.

> > If the class were called MathExpression,

> Call it Calculation instead. Expression would be more suitable if it had
> variables.

> > I'd like to be able to:

> > | aCalc |

> Man, you even call the var aCalc. Where did the MathExpression come from?

Who knows?

- Show quoted text -

Quote:

> > aCalc := MathExpression new: 0.15. " starts out with 0.15"
> > aCalc * 100.
> > aCalc printString. "0.15 * 100"
> > aCalc / 365.
> > aCalc printString. "(0.15 * 100) / 365"
> > aCalc * 60.
> > aCalc printString. "((0.15 * 100) / 365) * 60"
> > aCalc. "2.465748"

> That last line won't work because if you choose 'show it' or 'display it',
> you will get the #printString, but anyway.

> > It would be a hybrid of an OrderedCollection and a Number.

> No. It would be a hybrid of Tree and Block.

> > It would only
> > resolve itself when asked to (however that would happen).

> Send it #value to get the result of evaluating it. Optionally cache the
> value.

> > When it's the
> > target of a message send, it would simply store the operator and the
> operand.

> You mean, 'a binary message send', correct?

Yes.

- Show quoted text -

Quote:

> Create and return a new Calculation and let the receiver be the left
> operand.

> > An interesting side-affect may be to add comments to either its elements
> or to
> > Number (or Magnitude) so that I would actually know what each of the
> numbers
> > is.

> > aCalc := MathExpression new: (0.15 \'annual interest rate')
> > aCalc * 100 \'Loan Amount'.
> > aCalc printStringComments. "annual interest rate * Loan amount"

> How about:

> (Calculation with: 0.15) comment: 'annual interest rate' ;
>     * 100 ; comment: 'Loan amount' ;
>     printStringComments

> > .. or something along those lines.  The value increases when someone asks,
> > "How did you get to that number???"
> > If I used an adding machine, I could show them the tape, but I would have
> to
> > tell them what each of the numbers are.  When some of the numbers happen
> to be
> > the same (like if someone were borrowing $365) the adding machine's tape
> would
> > look confusing without accompanying narrative.

> > Does something like this already exist?

> Probably. Not worth searching for, though. Less than an hour to write, and
> then you'll really understand it.

True, but then I'd be hypocritical about reusing components if I didn't at
least try looking for something.  If I do a splendid job creating this others
will be able to use it.

Quote:> <snip>

> Tom, hope my comments are of some help. Do you want to develop it
> test-driven? If so, it would be nice to post your test cases and ask what
> other people here come up with.

I'll do that, but probably only as a followup in comp.lang.smalltalk, since by
then it will be mostly of interest to Smalltalkers.

--
.tom

 
 
 

A Class for recording mathematical expressions?

Post by Hans-Martin Mosne » Sat, 20 Oct 2001 01:31:48



> Why would I need to muck with the compiler stuffs?  I could perform the operation and save the result in that node.  If I did that, I would never have to worry about
> evaluating the string for a final result or for a partial result.

I wanted the complete structure preserved, and prettyprinting which the compiler nodes give me.
Of course, it's possible without that, but then you need to handle message precedences by yourself.
You might like the fact that things like this work, too:
        'hallo' symbolic asUppercase last
However, this does not work with the explain method because that does not handle unary messages yet.
And if you substitute the "last" with "at: 5" then you get a walkback since #at: is implemented in Object, so the symbolic value understands it and raises an error.

However, I think you get the idea...

Cheers,
Hans-Martin

 
 
 

1. Evaluating a Mathematical expression?

Chad,

 > Is there a Windows API call that can evaluate a Mathematical
 > expression that is within a string?

Sorry, no. I would recommend getting a decent lexer/parser generator (my
favorite is Antler).

--

Cheers,

Felix.

If you post a reply, kindly refrain from emailing it, too.

No anti-spam address here. Just one comment: IN YOUR FACE!

2. Anyone using HP35450A under OS/2 ???

3. evaluate a string as a mathematical expression

4. M102 with no system floppy

5. Mathematical Expression Parser has moved

6. Backup Exec 8.x IDR

7. parser for mathematical evaluation of expressions

8. Web exception occured when accessing web service from Cf

9. Optimizing Mathematical Expressions For Size

10. Help on parsing Mathematical expression

11. Binary Expression Tree with an infix expression

12. Does an expression-list contain expressions?

13. Defect Report: throw-expression in a constant expression