Design and Implementation of an expression computing case

Source: Internet
Author: User
Tags class operator

Author: Liu Yuan

Author Profile


Liu Yuan, male, software engineer, you can get in touch with the author through yliu@guanghua.sh.cn.

Problem cause


In my previous data collection system for network devices and hosts, some collected data needs to be computed before being saved into the database, rather than simply storing its original values. To provide users with maximum flexibility, I imagine a user interface that allows users to enter computing expressions (or calculation formulas ). In this way, in addition to complying with a small number of rules, users can enjoy the maximum flexibility.

What are the characteristics of such expressions? It is generally not a pure expression that can be computed immediately (for example, 1 + 2*3-4 ). It contains elements called variables. Variables generally have special internal syntaxes. For example, "@ totalmemory" may be used to indicate the total physical memory of a device or host (hereinafter referred to as a device, the expression "(@ totalmemory-@ freemory)/@ totalmemory * 100" indicates the current memory usage percentage of the device. If it is associated with the alarm system and the system sends a Warning when the value exceeds 80, this becomes a meaningful thing. Different types of collected data may have to undergo different computations before they are stored in the database. However, when final value is evaluated, the specific variables must be replaced with specific values (that is, the specific values collected). Otherwise, the expressions cannot be calculated. This process occurs during running.

General problems


I think expression computing is a general topic, and it is not a new topic. We may encounter it in many places. I wrote an expression conversion and computing program while I was studying. I have seen some report systems. Many of them support calculation formulas, whether they are independent, included in the MIS system or financial software. I think the formula in these systems is roughly the same as what I encountered. For me, I encountered this problem in the data collection project and may encounter it in other projects next time. Since more than once, I hope to find a general solution.

Some existing designs and implementations cannot meet the requirements


I am not satisfied with the design and implementation of the first version. Then I spent some time searching the Internet (Keyword: Expression suffix or Expression Infix Postfix ). It is disappointing that some programs found about expression conversion and calculation cannot meet my requirements. Many such programs only support pure expressions that can be computed immediately, and do not support variables. In addition, expression parsing and calculation are coupled and difficult to expand. Adding a new operator (or a new variable syntax) almost always changes the source code. In my opinion, this is the biggest defect (in fact, although I was proud to write the expression conversion and computing program, it now seems to have the same defect ). However, expression conversion and computation have mature and stack-based classical algorithms, which are discussed in many computer books or textbooks. The expressions that people write in the natural way are in the form of infix. First, we need to convert the infix expression into a suffix expression, and then calculate the value of the suffix expression. I plan to continue using this classic process and algorithm.

My design ideas and goals


Since the expression conversion and computing Core algorithms are mature, I am eager to extract them and remove (resolution-related) coupling! Imagine that if a thing has a relatively complete connotation and independence, it will produce this need, and it can also be expressed through formal separation and extraction. This process is inseparable from abstraction. I soon realized that I was actually designing a small framework for expression computing.

The expression must support the addition, subtraction, multiplication, division, and Division operators. It may also support square, square (sqrt), and triangular operators such as sin and cos. What if there are other operations, including custom operators? Are you sure you have fully considered it? Such as custom operators are completely existing and reasonable requirements. In the data collection system, I once considered introducing a diff operator to indicate the difference between the collection of the same cumulative type and the collection of the last two times (that is, the collection cycle. The above thinking prompted me to decide that the design of operators must be open. Users (this refers to user programmers, the same below) can be expanded to add new operators.

The expression can contain variables. Variables are supported throughout the entire process of expression parsing, conversion, and calculation. In the parsing phase, users should be allowed to use the variable syntax that suits them or her own. I should not implement variable recognition based on a specific syntax in advance.

It supports extensible operators, unknown variable syntax, and even basic numeric values (such as 123, 12.3456, 1.21E17) in theory, there are also various types and precision (Integer/Long/Float/Double/BigInteger/BigDecimal), which determines that a fixed expression parsing method cannot be provided. Expression parsing also requires scalability. The best result is an easy-to-use and scalable parsing framework. For new operators and variable syntaxes, you can expand on this framework to provide enhanced parsing capabilities. From an abstract perspective, the expressions I intend to support are composed of only four elements: parentheses (including left and right parentheses), operators, values, and variables. An expression string provided by an end user. After parsing, an internal expression may be generated to facilitate subsequent processing. Each element of this expression can only be one of the above four types.

Value


At first, I wrote a class that expresses numeric values, called Numeral. I am concerned about whether Numeral represents an integer, a floating-point number, or a double-precision number. In a vague sense, I hope it can express any of the above types and precise values. But I also hope that it can clearly express the specific type and precision value, if needed. Even when I think of Numeral, it is better to express BigInteger and BigDecimal (imagine that in some cases, we need to parse and calculate such an expression, which allows a large range of precision and range of values, so Long or Double can not be accommodated), otherwise we will be in trouble in special circumstances. In terms of scalability, numeric classes are not similar to operator classes. They should be mature and almost do not need to be extended.

After repeated attempts and chaos (Numeral was modified or even rewritten later), I found a wise way. Java. lang. Number is used directly as a numerical class (this is actually an interface ). Fortunately, in Java, Integer, Long, Float, Double, BigInteger, BigDecimal, and other numeric classes all implement java. lang. number (hereinafter referred to as Number) interface, the user views and uses Number as the type and precision, and has the right to control it/her, I should not determine the numerical type and accuracy in advance. The choice is expressed by the Number class, which seems to be the best choice with the lowest cost and maintains considerable flexibility. The Numeral class is deprecated as a subfolder.

Brackets


In expressions, the role played by parentheses cannot be ignored. It can change the natural priority of an operation and calculate it according to the user's desired order. I use the Bracket class to represent parentheses. This class can be seen as final because it does not need to be extended. Brackets are divided into brackets and right brackets. I use them as two static instance variables of the Bracket class (and only two instance variables of the Bracket class ).

Public class Bracket
{
Private String name;

Private Bracket (String name ){
This. name = name;
}

Public static final Bracket
LEFT_BRACKET = new Bracket ("("),
RIGHT_BRACKET = new Bracket (")");

Public String toString (){
Return name;
}
}

 


Operator


The design requirements for operators are open, which almost immediately means they must be abstract. I hesitated to define the operator as an interface or an abstract class, and finally I chose an abstract class.

Public abstract class Operator
{
Private String name;

Protected Operator (String name ){
This. name = name;
}

Public abstract int getDimension ();

Public abstract Number eval (Number [] oprands, int offset );
// Throws ArithmeticException?

Public Number eval (Number [] oprands ){
Return eval (oprands, 0 );
}

Public String toString (){
Return name;
}
}

 


This operator is designed to contain two main interface methods. The getDimention () interface conveys the following information: What is the operator? That is, several operands are required. Obviously, the most common operators are unary and binary operators. This interface method also seems to allow more operators than binary, but I have not made a deeper look at operators than binary. I am not sure whether the conversion and computing algorithms based on Stack expressions fully support binary or above operators. Despite this concern, I still keep the current interface method.

The main interface method of operators is eval (), which is the computing interface of operators and reflects the essence of operators. In this interface method, we need to pass all the required operands to it. If the operator is several yuan, we need several operands, which should be consistent. Then, perform computation that matches the meaning of the operator and return the result. If a new operator is added, You need to implement the preceding operation method of the operator.

Variable

In a sense, a variable is a "value to be determined ". Should I design a Variable class (or interface )? I did. When are variables replaced by specific values? I don't know these processes and should leave them to users for processing. I have almost no knowledge about variables, so the Variable class has little significance. If this class/interface is retained and a restriction is imposed on the user, he/she must inherit or implement the Varibale class/interface, so soon

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.