gpt4 book ai didi

c - 当 long-double 计算器失去精度时?

转载 作者:太空宇宙 更新时间:2023-11-04 01:55:56 27 4
gpt4 key购买 nike

我的任务是为在 long double 上运行的计算器编写代码。事实证明,在某个点之后,计算器会失去精度。例如,它计算正确 9999999 ^ 2,但就 99999999 ^ 2 而言,它产生的结果比应有的大 1。我已经阅读了一些关于浮点精度的内容,但所有问题都与小数有关。我知道可以使用 gmp 库修复它,但我的问题是:

Is there any other way to tackle this problem?
How to calculate/show the point to which a long double calculator is accurate?

ma​​in.c

int main(int argc, char *argv[])
{
char str[100];
char key[] = "exit";

if (argc > 1)
{
switch (argv[1][1])
{
case 'V': case 'v':
setValid(1);
break;
case 'E': case 'e':
setError(1);
break;
default:
setValid(1);
break;
}
}
else
setValid(1);

while (gets(str) != NULL && strcmp(key, str) != 0)
{
if (calcFilter(str));
else
printf("expression error!\n");
}

return 0;
}

evalexpression.c

static long double f1, f2;
static char op;

int isValidExpression(const char *str)
{
int res;
char ops[10];

res = sscanf(str, "%Lf %s %Lf", &f1, ops, &f2);

if (res == 3 && (ops[0] == '+' || ops[0] == '*' || ops[0] == '-' ||
ops[0] == '/' || ops[0] == '^'))
{
op = ops[0];
return 1;
}
else
return 0;

long double getExprValue(void)
{
switch (op)
{
case '+':
return (f1+f2);
case '*':
return (f1*f2);
case '-':
return (f1-f2);
case '/':
return (f1/f2);
case '^':
return (pow(f1, f2));
default:
perror("something went wrong");
return 0;
}
}

计算过滤器.c

static int errorsw = 0, validsw = 0;

int calcFilter(const char *str)
{
if (validsw == 1 && isValidExpression(str))
{
printf("%s = %Lf\n", str, getExprValue());
return 1;
}
else if (errorsw == 1 && !isValidExpression(str))
{
printf("%s\n", str);
return 1;
}
else if (errorsw)
return 1;
else
return 0;
}

void setError(int mode)
{
errorsw = mode;
}

void setValid(int mode)
{
validsw = mode;
}

最佳答案

使用 pow(f1, f2)适得其反,因为将参数转换为 double打电话前pow()并解释了 OP 的困境。 double通常在 OP 的情况下以 16 位十进制数字开头有问题。推荐powl()

// return (pow(f1, f2));
return (powl(f1, f2));

其他说明:

long double可以用 LDBL_DIG 精确编码数字十进制数字。在您的机器上这至少是 10,可能是 18+。

long double ,打印时需要LDBL_DECIMAL_DIG输出的有效数字,以将该数字与所有其他数字区分开来 long double .要查看所有意义,请避免使用 %Lf在尝试确定与精度相关的问题时。

printf("%.*Le", LDBL_DECIMAL_DIG - 1, x);   // "%Le"

另见 Printf width specifier to maintain precision of floating-point value


[编辑] float 何时会失去精度?

* /简单。只要结果不是那么小(低于正常值)或溢出,答案应该是 0.5 ULP ( unit in the last place )。

+ -当结果离零更远时,再次损失最多 0.5 ULP。但是当有像1.0 - 0.9999999...这样的取消时, 几乎所有的精度都会丢失。

z=pow(x,y) z 时可能非常不精确是一个很大的数字并且函数写得不好,例如当简单地使用数学恒等式时:z = exp(log(x)*y) .否则很好pow()结果将在 1.0 ULP 以内。


@M.M comments这是使用 powl() 的替代方法是#include <tgmath.h>用于自动正确选择多个 <math.h>功能。

关于c - 当 long-double 计算器失去精度时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34322932/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com