varch/doc/calculate.en.md

4.4 KiB

Introduction

This module is a simple parser and calculator for mathematical expressions. By passing in a simple arithmetic expression, it calculates the result.

Interface

Expression Calculation

double calculate(const char *expression);

This function is very simple to use: pass in the expression, and it returns the calculation result. The default return type is double precision floating-point, which has a wide range and is suitable for floating-point calculations. When there is a calculation error, it returns NAN.
The supported operators include: addition +, subtraction -, multiplication *, division /, exponentiation ^, and modulus %. The operator precedence is as follows:

Operator Precedence
^ 0
* / % 1
+ - 2

In addition to basic arithmetic operations, built-in functions are also supported. The function name is followed by (), where the function parameters are passed inside the parentheses, and multiple parameters are separated by commas ,.

Function Parameters Description
abs 1 Absolute value
sqrt 1 Square root
exp 1 Natural exponential
ln 1 Natural logarithm
sin 1 Sine
cos 1 Cosine
tan 1 Tangent
cot 1 Cotangent
asin 1 Arcsine
acos 1 Arccosine
atan 1 Arctangent
acot 1 Arccotangent
ceil 1 Ceiling
floor 1 Floor
min 2 Minimum of two
max 2 Maximum of two
pow 2 Power function, same as ^
log 2 Logarithm function

Additionally, there are constants pi and e, which are case-insensitive.
Spaces may be retained between operators and numbers for clarity, but numbers must be tightly combined into a single number.

Simple examples:

static void test_base(void)
{
    const char *expression[] = {
        "    ( 99 * 3 ) ",
        "  min  (12, 3)",
        "sin (  11 / 2 *  pi ) + 100 ",
    };

    for (int i = 0; i < sizeof(expression) / sizeof(expression[0]); i++)
    {
        printf("cal: %s = %lf\r\n", expression[i], calculate(expression[i]));
    }
}

Calculation results:

cal:     ( 99 * 3 )  = 297.000000
cal:   min  (12, 3) = 3.000000
cal: sin (  11 / 2 *  Pi ) + 100  = 99.000000

You can export this calculation module as a command to execute calculations in command form. This command function has already removed unnecessary trailing zeros after the decimal point for a more aesthetically pleasing display.

static int command_calculate(const char *expression)
{
    double r = NAN;
    if (!expression) return 0;
    r = calculate(expression);
    if (fabs(floor(r) - r) <= DBL_EPSILON && fabs(r) < 1.0e60) printf("%.0lf\r\n", r);
    else if (fabs(r) < 1.0e-6 || fabs(r) > 1.0e9) printf("%e\r\n", r);
    else 
    {
        char p[64];
        int len = 0;
        len = sprintf(p, "%lf", r);
        while (len > 0 && p[len-1] == '0' && p[len-2] != '.') {p[--len] = 0;}
        printf("%s\r\n", p);
    }
    return 1;
}

Input command:

calculate -c "sin( 11 / 2 * Pi ) + 2 ^ 3"

Calculation result:

7

Exporting

int calculate_function(const char *name, double (*func)(), int argc); // Export function
int calculate_constant(const char *name, double value); // Export constant

These two methods export functions and constants, respectively.

To export a function, you pass in the function name, function pointer, and the number of parameters. It supports exporting up to CALCULATE_EXFUNC_MAX functions.

To export a constant, you pass in the constant name and constant value, supporting up to CALCULATE_CONSTV_MAX constants.

List Key Identifiers

const char* calculate_ls_func(int *argc); // List functions
const char* calculate_ls_const(double *value); // List constants

These two methods list functions and constants, respectively.

Both use an iterative list method that continues until NULL is returned.