C 中的 eval 函数导致负数

eval function in C resulting in negative

我正在使用java11,EclipseIDE。 我正在设计一个需要一些计算的程序,我正在 java 中编写该程序,所以我试图找到类似于一个名为 "eval()" 的函数的东西,它计算一个方程。因此,我在 C 中实现了该功能并将其转换为“.dll”文件并在 java.

中使用它

我的主要问题是当我将等式传递给 eval 函数时,它 returns 是一个负数且非常大的双精度数,例如:我将它传递给“1.0+0.5^2”,它结果为“-9.255963134931783E61”,不可能得到这样的结果!

注意:它总是返回正确的结果,但在最后一次执行时,它返回了上面的结果!为什么?如何?我正在使用相同的 eval 函数。

我只给你看重要的部分,剩下的不重要:

所有代码:

eval.c :

int evaluate(char* line, double* val);
static int do_op(void);
static int do_paren(void);
static void push_op(char op);
static void push_arg(double arg);
static STATUS pop_arg(double* arg);
static STATUS pop_op(int* op);
static char* getexp(char* str);
static char* getop(char* str);
static char* getop(char* str);
JNIEXPORT jdouble JNICALL Java_application_Main_eval
(JNIEnv* env, jobject object, jstring str) {
    const char* strs = env->GetStringUTFChars(str, false);
    char* equation = const_cast<char*>(strs);
    double result;
    evaluate(equation, &result);
    printf("the result is : %f", result);
    jdouble* returnResult = new jdouble(result);
    return *returnResult;
}

java 中的原生 eval 方法:

static {
    System.load(System.getProperty("user.dir")+"\eval.dll");
}
public native double eval(String equation);

java 方法最后导致了一些奇怪的事情:

String evaluateEquation(String e) {
        // we will truncate the brackets into pieces and eval every piece, 
        // and then return it without brackets by replacing it inside the equation!
        StringBuilder equation = new StringBuilder(e);
        int count = countBrackets(equation);
        int[] pos;
        String part;
        String result;
        // TODO : fix here : 
        BigDecimal tempResult = new BigDecimal(0);
        while (count!=0) { // every one loop, it will truncate, evaluate, replace the new value!
            pos = lastBrackets(equation.toString());
            part = equation.substring(pos[0], pos[1]+1);
            System.out.println("evaluating this part : "+part);
            tempResult = new BigDecimal(new Main().eval(part));
            System.out.println(tempResult.toString());
            result = truncateDecimals(tempResult);
            equation.replace(pos[0], pos[1]+1, result);
            System.out.println(equation.toString());
            count--;
        }
        System.out.println(equation.substring(0, equation.length()));
        part = equation.substring(0, equation.length()-1);
        finalResult = new BigDecimal(new Main().eval(part));
        System.out.println("FinalResult is : "+truncateDecimals(finalResult));
        return truncateDecimals(finalResult);
    }

如果您读过 "eval.c" 程序,您会注意到它需要一个 "char*" 和一个 "double&"。我已经处理了这些转换,我认为它们与这个错误有关。该方法总是 returns 正确的结果,除了一个地方,即在 "evaluateEquation" 方法的末尾。

据我所知,存储在计算机内存中的任何数字只有在我们将其更改为负数或超出其最大存储数时才会变为负数。如果数字超出限制,它将变成负数。 但是,我注意到一些事情,每次我在 "evaluateEquation" 函数末尾调用 eval 函数时,负数都会一次又一次地重复,我得到相同的结果,即:“-9.255963134931783E61”。 如果你有任何假设、解释或任何东西。请随意谈谈。我永远不会对任何试图帮助我的人投反对票。

注意:这是我用来制作 dll 文件的原始 C 代码:http://stjarnhimlen.se/snippets/eval.c

数字 -9.255963134931783E61 具有内部表示 0xCCCCCCCCCCCCCCCC,这强烈表明它是一个未初始化的值。

由于您没有检查 evaluate 中的 return 值,这表明它是 return 错误条件,因为在那种情况下,evaluate不设置其第二个参数指向的值。

我注意到代码遗漏了一些东西。我修改了一下,我记得一个dll文件只在程序启动时加载一次,所以所有的变量都被删除或清理了。导致返回值为奇数,并在使用数组满后不断重复。所以,我创建了一个函数来清除:

void clear() {
    for (int i = 0; i!=256 ; i++) {
        op_stack[i] = NULL;
        arg_stack[i] = NULL;
        token[i] = NULL;
    }
    op_sptr = 0;
    arg_sptr = 0;
    parens = 0;
    state = 0;
}