__FLT_MAX__ 和 __DBL_MAX__ 到 0?
__FLT_MAX__ and __DBL_MAX__ to 0?
在 GCC 9.1 中,当使用浮点类型调用 std::numeric_limits 的函数时,它们在大多数情况下 return 0。
这发生在我正在处理的项目中,MSVC、GCC 8.3 或 Clang 8.0 没有问题。 <double>::epsilon()
有时有一个正确的值,但是当从其他文件调用时它也可能计算为 0。
// Commented values at the end of the lines are the values given by the debugger
// Making the variable constexpr doesn't change their values
auto intMax = std::numeric_limits<int>::max(); // {int} 2147483647
auto floatMax = std::numeric_limits<float>::max(); // {float} 0
auto floatEpsilon = std::numeric_limits<float>::epsilon(); // {float} 0
auto floatMin = std::numeric_limits<float>::min(); // {float} 0
auto floatLowest = std::numeric_limits<float>::lowest(); // {float} -0
auto doubleMax = std::numeric_limits<double>::max(); // {double} 0
auto doubleEpsilon = std::numeric_limits<double>::epsilon(); // {double} 2.2204460492503131e-16
auto doubleMin = std::numeric_limits<double>::min(); // {double} 0
auto doubleLowest = std::numeric_limits<double>::lowest(); // {double} -0
std::cout << std::setprecision(10) << std::fixed
<< "Max int = " << std::numeric_limits<int>::max()
<< "\n"
<< "\nMax float = " << std::numeric_limits<float>::max()
<< "\nEpsilon float = " << std::numeric_limits<float>::epsilon()
<< "\nMin float = " << std::numeric_limits<float>::min()
<< "\nLowest float = " << std::numeric_limits<float>::lowest()
<< "\n"
<< "\nMax double = " << std::numeric_limits<double>::max()
<< "\nEpsilon double = " << std::numeric_limits<double>::epsilon()
<< "\nMin double = " << std::numeric_limits<double>::min()
<< "\nLowest double = " << std::numeric_limits<double>::lowest() << std::endl;
(<int>::max()
留作参考)
结果独立文件(正确值):
Max int = 2147483647
Max float = 3.40282e+38
Epsilon float = 1.19209e-07
Min float = 1.17549e-38
Lowest float = -3.40282e+38
Max double = 1.79769e+308
Epsilon double = 2.22045e-16
Min double = 2.22507e-308
Lowest double = -1.79769e+308
项目成果:
Max int = 2147483647
Max float = 0
Epsilon float = 0
Min float = 0
Lowest float = -0
Max double = 0
Epsilon double = 2.22045e-16
Min double = 0
Lowest double = -0
独立编译专用文件时,值是正确的:问题不是来自 GCC(无论如何我都预料到了),但很可能是来自项目的配置。
编辑:独立编译项目文件(目前出现此问题)也给出了正确的结果。使用 gcc -dM -E
,__DBL_MAX__
被定义为 double(1.79769313486231570814527423731704357e+308L)
。
__DBL_MAX__
值已定义,执行 ifdef 包围的代码:
#ifdef __DBL_MAX__
#pragma message "__DBL_MAX__ defined"
#endif
/*
note: #pragma message: __DBL_MAX__ defined
40 | #pragma message "__DBL_MAX__ defined"
| ^~~~~~~~~~~~~~~~~~~~~
*/
GDB给出了相同的精确值,所以输出部分没有问题。输出 XXX_YYY
或 __XXX_YYY__
给出相同的结果,因为 numeric_limits' 函数无论如何都会调用它们。
100%清楚:std::numeric_limits<double>::max() == 0
return是真的,所以输出部分没有问题。它只是留在这里作为参考。
GCC 产生这种行为的原因可能是什么? __XXX_YYY__
不是内置值吗?他们怎么可能持有0?
所以错误来自(至少间接地)预编译 headers,我们将其与 CMake 的 cotire 一起使用。
那些 headers 包含的每个文件,手动单独包含在 "problematic" 文件中,都没有重现该问题。
虽然有点奇怪,但目前除了cotire我还没有看到任何可行的解释。根据这个线程,显然已经有报道称它存在限制问题:C++ Cmake build with cotire and gtest - error with float.h
临时解决方案是使用 GCC 9.1+ 禁用预编译 headers。如果有人遇到同样的问题,如果您知道为什么会发生这种情况以及如何发生,请随时添加评论或回答。
感谢 Giovanni、Kamil 和评论中的 n.m,他们引导我走向正确的方向!
在 GCC 9.1 中,当使用浮点类型调用 std::numeric_limits 的函数时,它们在大多数情况下 return 0。
这发生在我正在处理的项目中,MSVC、GCC 8.3 或 Clang 8.0 没有问题。 <double>::epsilon()
有时有一个正确的值,但是当从其他文件调用时它也可能计算为 0。
// Commented values at the end of the lines are the values given by the debugger
// Making the variable constexpr doesn't change their values
auto intMax = std::numeric_limits<int>::max(); // {int} 2147483647
auto floatMax = std::numeric_limits<float>::max(); // {float} 0
auto floatEpsilon = std::numeric_limits<float>::epsilon(); // {float} 0
auto floatMin = std::numeric_limits<float>::min(); // {float} 0
auto floatLowest = std::numeric_limits<float>::lowest(); // {float} -0
auto doubleMax = std::numeric_limits<double>::max(); // {double} 0
auto doubleEpsilon = std::numeric_limits<double>::epsilon(); // {double} 2.2204460492503131e-16
auto doubleMin = std::numeric_limits<double>::min(); // {double} 0
auto doubleLowest = std::numeric_limits<double>::lowest(); // {double} -0
std::cout << std::setprecision(10) << std::fixed
<< "Max int = " << std::numeric_limits<int>::max()
<< "\n"
<< "\nMax float = " << std::numeric_limits<float>::max()
<< "\nEpsilon float = " << std::numeric_limits<float>::epsilon()
<< "\nMin float = " << std::numeric_limits<float>::min()
<< "\nLowest float = " << std::numeric_limits<float>::lowest()
<< "\n"
<< "\nMax double = " << std::numeric_limits<double>::max()
<< "\nEpsilon double = " << std::numeric_limits<double>::epsilon()
<< "\nMin double = " << std::numeric_limits<double>::min()
<< "\nLowest double = " << std::numeric_limits<double>::lowest() << std::endl;
(<int>::max()
留作参考)
结果独立文件(正确值):
Max int = 2147483647
Max float = 3.40282e+38
Epsilon float = 1.19209e-07
Min float = 1.17549e-38
Lowest float = -3.40282e+38
Max double = 1.79769e+308
Epsilon double = 2.22045e-16
Min double = 2.22507e-308
Lowest double = -1.79769e+308
项目成果:
Max int = 2147483647
Max float = 0
Epsilon float = 0
Min float = 0
Lowest float = -0
Max double = 0
Epsilon double = 2.22045e-16
Min double = 0
Lowest double = -0
独立编译专用文件时,值是正确的:问题不是来自 GCC(无论如何我都预料到了),但很可能是来自项目的配置。
编辑:独立编译项目文件(目前出现此问题)也给出了正确的结果。使用 gcc -dM -E
,__DBL_MAX__
被定义为 double(1.79769313486231570814527423731704357e+308L)
。
__DBL_MAX__
值已定义,执行 ifdef 包围的代码:
#ifdef __DBL_MAX__
#pragma message "__DBL_MAX__ defined"
#endif
/*
note: #pragma message: __DBL_MAX__ defined
40 | #pragma message "__DBL_MAX__ defined"
| ^~~~~~~~~~~~~~~~~~~~~
*/
GDB给出了相同的精确值,所以输出部分没有问题。输出 XXX_YYY
或 __XXX_YYY__
给出相同的结果,因为 numeric_limits' 函数无论如何都会调用它们。
100%清楚:std::numeric_limits<double>::max() == 0
return是真的,所以输出部分没有问题。它只是留在这里作为参考。
GCC 产生这种行为的原因可能是什么? __XXX_YYY__
不是内置值吗?他们怎么可能持有0?
所以错误来自(至少间接地)预编译 headers,我们将其与 CMake 的 cotire 一起使用。
那些 headers 包含的每个文件,手动单独包含在 "problematic" 文件中,都没有重现该问题。
虽然有点奇怪,但目前除了cotire我还没有看到任何可行的解释。根据这个线程,显然已经有报道称它存在限制问题:C++ Cmake build with cotire and gtest - error with float.h
临时解决方案是使用 GCC 9.1+ 禁用预编译 headers。如果有人遇到同样的问题,如果您知道为什么会发生这种情况以及如何发生,请随时添加评论或回答。
感谢 Giovanni、Kamil 和评论中的 n.m,他们引导我走向正确的方向!