为了获得更好的小数精度,我决定使用" 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)上运行我的程序时,它仍然像双重一样四舍五入,给我不那么精确的答案。应该怎么做才能避免这种情况?
答案 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;
}