【问题标题】:GMP library in C - How to make the addition more precise?C 中的 GMP 库 - 如何使加法更精确?
【发布时间】:2017-06-12 09:25:53
【问题描述】:

尝试使用 C 上的 GMP 库创建一个简单的精确计算器,在测试我的程序时遇到了一个相当意外的错误; 2 + 2.22222 = 4.22221999999999999999。

这是我在 GMP 中使用的函数;

mpf_add(res, f1, f2); //with res as result already initilized, f1 and f2 as the values

关于打印功能;

gmp_printf("%.Ff\n", getExprValue()) //with getExprValue the calculating function that has the line above.

编辑:

这是完整的代码;

    int isValidExpression(const char *str) // to check the input
{
    int res;
    char validOps[6] = {'+', '-', '*', '/', '^', '\0' };

    mpf_init(f1);
    mpf_init(f2);

    // RES = 3 WHEN SYNTAX OK
    res = gmp_sscanf(str, "%Ff %c %Ff", f1, &op, f2);

    // RES = 4 WHEN OPERAND OK
    if(strchr(validOps, op)) res++;

    int exprCounter = 0;
    char* token = strtok(str, " +-*/^");
    while(token != NULL)
    {
        // TOO MANY WORDS IN THE EXPRESSION
        ++exprCounter;
        if(exprCounter > 2) res = 0;

        // TAKE THE NEXT WORD
        token = strtok(NULL, " +-*/^");
    }
    return (res==4);
}
mpf_t* getExprValue() //Working on the operand
{
    static mpf_t res;
    mpf_init(res);


    switch(op)
    {
    case '+':
        mpf_add(res, f1, f2);
        break;

    case '-':
        mpf_sub(res, f1, f2);
        break;

    case '*':
        mpf_mul(res, f1, f2);
        break;

    case '/':
        mpf_sgn(f2) != 0 ? mpf_div(res, f1, f2) : printf("Division by ");
        break;

    case '^':
        mpf_pow_ui(res, f1, mpf_get_si(f2));
        break;
    }
    return res;
}

至于主要的;

char input[MAX_INPUT];
while(gets(input))
{
    if(strcmp(input, "exit") != 0)
    {
        isValidExpression(input) ? gmp_printf("%.Ff\n", getExprValue()) : puts("Expression error");

    }
    else
    {
        puts("Exiting...");
        break;
    }
}

【问题讨论】:

  • 如果您能给我们一个完整的代码示例,这可能会有所帮助...
  • @unwind 没有问题。不过,输入类型会很有趣。 OP 应该知道浮点并不总是 100% 准确,无论它有多少精度。
  • 32位浮点数只能存储2**32不同的值,一个double只能存储2**64不同的值,这仍然是事实。无论您为此付出多大的意义,它仍然适用。浮点数始终是范围和精度之间的权衡。准确表示它们的一种方法是存储 两个 整数值来表示分数。
  • 十进制值 2.22222 不能用二进制浮点数精确表示,即使是无限精度。出于同样的原因,1/3 不能精确地表示为小数。这不是精确度的问题,而是表示的问题。您可能想阅读speleotrove.com/decimal
  • 不要在任何新项目中使用 GMP 的 mpf_t,它被 MPFR 的 mpfr_t 取代。他们的网页也有几个十进制数库的链接。如果您的编译器支持,您也可以考虑像 _Decimal64 这样的类型。根据您的目标,Rationals 也可能是一种选择。

标签: c calculator precision addition gmp


【解决方案1】:

问题是您正在尝试十进制算术并使用浮点数。您需要使用十进制算术库对十进制数进行精确计算。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    相关资源
    最近更新 更多