如何在编译时检测long double是否具有扩展精度

8

在一些系统上,double类型和long double 类型是相同的。如何在编译时检测 long double 的扩展精度是否高于 double,并将其用于条件编译?

我发现libgcc中存在预定义的宏 SIZEOF_DOUBLE 和 SIZEOF_LONG_DOUBLE,但这些宏在不同的工具链之间不可移植。

有没有C语言的方法来解决这个问题?


你可以尝试使用 sizeof(double) > 8。虽然这种方法也不是完全可移植的,但在大多数情况下它仍然有效。 - Mysticial
你不能测试 sizeof(double) < sizeof(long double) 吗?还是我漏了什么? - Seth Carnegie
3
预处理器不识别 sizeof - Keith Thompson
1
只是好奇,你将如何使用这些信息? - Keith Thompson
我正在实现一些双精度函数,为了验证它们,我需要长双精度,但长双精度并不总是扩展精度。如果长双精度与双精度相同,我将使用mpfr库作为参考。 - kanna
4个回答

7
你可以从 float.h 中比较 DBL_MANT_DIGLDBL_MANT_DIG

2
你可以进行测试,例如:
#if DBL_MANT_DIG < LDBL_MANT_DIG

或者在float.h中定义的类似值


0

这个问题的“正确”解决方案(许多项目都在使用)是创建一个配置脚本。

配置脚本运行各种测试,包括编译和运行小程序以确定编译器和系统属性。然后,该脚本将其发现写入头文件或makefile,或两者兼备。当然,你的脚本可以做任何你想要的事情。

有一些工具可以半自动地完成这种事情,但它们可能对你来说过于复杂了。如果你想看看它们的名称是autoconfautomake。请注意,它们不容易学习,但它们生成的配置脚本和makefile应该可以在任何平台上工作,只要它具有类Unix shell和GNU make。


-1
为什么你需要使用long double?是为了精度。因此,直接进入问题的核心并测试精度,由EPSILON指定:
#include <float.h>
printf("Info: long double epsilon = %10.4Lg\n", LDBL_EPSILON);
if (LDBL_EPSILON > 1.2e-19) {
    printf("Insufficient precision of long double type\n");
    return 1;
}

这只是一个运行时测试,而不是配置或编译时的测试。

将其放在单元测试中或放在一个小的测试程序中,在CMake中运行(如ams所提出的答案)。


1
"...在编译时"和"if (LDBL_EPSILON > 1.2e-19)"是运行时表达式,你不能在编译时(在预处理器中)比较浮点数。" - KamilCuk
True。我会把它放在第一个单元测试中,或者在从CMake运行的测试程序中运行。 - Joachim W
@KamilCuk 我修改了我的答案以反映您的反对意见。谢谢。 - Joachim W

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接