C++ 使用gcc编译时PowerPC上的长双精度错误

C++ 使用gcc编译时PowerPC上的长双精度错误,c++,gcc,floating-point,powerpc,long-double,C++,Gcc,Floating Point,Powerpc,Long Double,当我给longdouble变量类型赋值时,我遇到了一个奇怪的错误。(PowerPC体系结构,gcc v4.9.2) 具体而言: const constexpr long double DEGREE_TO_RAD = 0.0174532925199432954743716805978693; const constexpr long double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD; 似乎会导致以下编译器错误: error: ‘(1.0e+0l / 1.7453

当我给
longdouble
变量类型赋值时,我遇到了一个奇怪的错误。(PowerPC体系结构,gcc v4.9.2)

具体而言:

const constexpr long double DEGREE_TO_RAD = 0.0174532925199432954743716805978693;
const constexpr long double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD;
似乎会导致以下编译器错误:

error: ‘(1.0e+0l / 1.74532925199432954743716805978693e-2l)’ is not a constant expression
 const constexpr long double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD;
我不是C++专家。这是我试图为我的开发机器环境专门构建的软件。然而,我的研究让我发现了以下的趣闻:

在某些PowerPC和SPARCv9机器上,
long double
作为双精度算法实现,其中
long double
值被视为两个双精度值的精确和,给出至少106位精度;使用这种格式,
长双精度
类型不符合IEEE浮点标准。否则,
long double
只是
double
(双精度)的同义词

这让我相信构建失败是由于我的体系结构与标准x86有不同的解释。将源代码中的
long double
更改为
double
,可以成功编译。这是巧合吗?为什么g++会在这个实例中对此大发雷霆?

这是一个与
constexpr
相关的bug(或者多个bug)。PowerPC的叮当声没有任何问题。如果您删除了
constexpr
,那么GCC也会在和中正确编译它


关于这个bug,第一个问题可以从GCC的错误消息中看到

源文件中没有
L
后缀,但不知何故它出现在错误输出中。如果我通过添加后缀来纠正代码,它仍然会失败,原因也是一样的。我没有针对PowerPC的更新版本的GCC,因此无法验证这一点,但错误发生在

确实,PowerPC在默认情况下使用,但浮点格式只是对用户透明的内部实现细节。它不应影响正确代码的编译。大多数嵌入式系统不支持浮点运算,大多数当前平台也没有128位
长双精度
的硬件。它们都使用软件进行这些操作,但浮点代码仍然可以在它们上面很好地编译。无论采用何种格式,都应编译有效代码,并且

如果我想的话,它们确实有用。在这里,您还可以清楚地看到使用和不使用
L
后缀之间的区别,因为没有它,文本是
double
,在向上转换为
long double
之前,将以
double
的精度构造,这意味着您将丢失双精度以外的所有数字如果不使用
double

.LC0:    # 1./0.0174532925199432954743716805978693
        .long   1074055773
        .long   3248897055
        .long   2108954270
        .long   2705146754
.LC1:    # 1.L/0.0174532925199432954743716805978693L
        .long   1074055773
        .long   3248897055
        .long   2108954270
        .long   2705146739

这些常量在使用时是相同的

这不是你的问题,但我会从
pi
的单个定义中计算所有常量,并为宏保留所有大写字母。对常量使用这种约定是Java/Python的事情。这些语言没有预处理器。出于某些奇怪的原因,在powerpc编译器的godbolt上
const constexpr long double RAD\u TO_DEGREE=pow(DEGREE\u TO_RAD,-1.0l)工作。。。而在x86上,叮当声将以
pow
作为非常量函数的形式消失,gcc以任何方式工作。不幸的是,我没有任何解释,
1.0l/
在我看来是可以在编译时明确计算出来的东西,即使有一些轻微的精度损失的风险,如果不明确指出某些不准确的地方,这可能值得警告。为什么不删除
constexpr
。可能的重复项。@PeteBecker&@M.M:我看到了同样的情况,没有使用powerpc64le编译器指定
-frounding math
。所以,也许不是dup。
.LC0:    # 1./0.0174532925199432954743716805978693
        .long   1074055773
        .long   3248897055
        .long   2108954270
        .long   2705146754
.LC1:    # 1.L/0.0174532925199432954743716805978693L
        .long   1074055773
        .long   3248897055
        .long   2108954270
        .long   2705146739