小数点错误

时间:2014-11-10 16:10:05

标签: c++ double long-integer

为了获得更好的小数精度,我决定使用" long double"在我的C ++代码中。但即使是以下代码:

long double a=5;
long double b=0.54645;
long double c=a*b;
printf("%Lf\n", c);

在我的电脑上生成-0.00000。我认为这是编译器的错误,正如答案所指出的那样。

动机是:我正在处理很多双打,将它们相乘然后添加结果。在添加时,我需要得到最终答案,距离正确答案不到1e-6。但由于精度问题,使用双打可能会给我一个错误的答案。错误的回答,我的意思是超过1e-6。所以,我决定使用长双打。

但是另一个事实引起了我的注意,那就是:当我使用长双打并在一个在线IDE(ideone.com)上运行我的程序时,它仍然像双重一样四舍五入,给我不那么精确的答案。应该怎么做才能避免这种情况?

1 个答案:

答案 0 :(得分:4)

您的程序在我的系统上正常工作(在删除无关紧要的事件后);输出是:

5.000000
0.546450
2.732250

如果我将%Lf格式更改为%f(这是不正确的),我会得到0.00000

我认为您正在使用MinGW,这是一个使用gcc编译器和Microsoft运行时库的Windows C实现。 (如果您使用MinGW,则此答案的其余部分不正确。)

MinGW有一个已知错误:它不能始终处理long double。 gcc将long double更广泛的类型视为范围和精度高于double;如果我没记错的话,微软的运行时库将它视为与double具有相同大小,范围和精度的类型。

任何一种表示都是完全有效的,但在单个实现中将两者结合会产生这种错误。这不是gcc或Microsoft实现中的错误;这是MinGW合并它们的一个错误。

只要不调用任何库函数,就可以使用long double执行计算并获得一致的结果。但是,如果您尝试使用Microsoft的long double打印printf,则会得到不一致的结果。

据推测,同样的问题适用于<math.h>中的函数。

如果您正在使用MinGW,最好只是避免使用long double,并确定double的较小范围和精度(这与您获得的范围和精度相同)无论如何,在纯Microsoft的实现中使用long double。)


顺便提一下,你的自包含程序比它需要的要大得多;绝大多数与你提出的问题完全无关。并且freopen调用会阻止输出显示。你有一个评论:

//Remember to remove freopen

但你留下了电话。

这是一个较小的版本:

#include <cstdio>
int main()
{
    long double a=5;
    long double b=0.54645;
    long double c=a*b;
    printf("%Lf\n", a);
    printf("%Lf\n", b);
    printf("%Lf\n", c);
    return 0;
}