0xb*_*00d 24 c++ floating-point epsilon c++17
float有没有办法获得小于 的浮点类型可表示的最大值1。
我看过以下定义:
static const double DoubleOneMinusEpsilon = 0x1.fffffffffffffp-1;
static const float FloatOneMinusEpsilon = 0x1.fffffep-1;
Run Code Online (Sandbox Code Playgroud)
但这真的是我们应该如何定义这些价值观吗?
根据标准,std::numeric_limits<T>::epsilon是机器 epsilon,即 1.0 与浮点类型可表示的下一个值之间的差T。但这并不一定意味着定义T(1) - std::numeric_limits<T>::epsilon会更好。
Adr*_*ica 26
您可以使用std::nextafter函数,尽管它的名称如此,但它可以通过使用适当的参数来检索在算术上在给定起点之前的下一个可表示值to。(通常-Infinity、0、 或+Infinity)。
根据 的定义nextafter,无论您的 C++ 实现使用什么浮点格式,这都是可移植的。(二进制与十进制,或尾数的宽度,又称有效数,或其他任何东西。)
示例:检索类型的小于 1 的最接近值double(在 Windows 上,使用 Visual Studio 2019 中的 clang-cl 编译器),答案与计算结果不同1 - \xce\xb5(如注释中所述,对于 IEEE754 数字来说是不正确的) ;在 2 的任意幂以下,可表示的数字的接近程度是其以上的两倍):
#include <iostream>\n#include <iomanip>\n#include <cmath>\n#include <limits>\n\nint main()\n{\n double naft = std::nextafter(1.0, 0.0);\n std::cout << std::fixed << std::setprecision(20);\n std::cout << naft << \'\\n\';\n double neps = 1.0 - std::numeric_limits<double>::epsilon();\n std::cout << neps << \'\\n\';\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n输出:
\n0.99999999999999988898\n0.99999999999999977796\nRun Code Online (Sandbox Code Playgroud)\n使用不同的输出格式,这可以打印为0x1.fffffffffffffp-1and 0x1.ffffffffffffep-1( 1 - \xce\xb5)
请注意,当使用类似技术确定大于 的最接近值时, 1调用nextafter(1.0, 10000.)将给出与计算相同的值1 + \xce\xb5(1.00000000000000022204),正如 \xce\xb5 的定义所预期的那样。
C++23 要求std::nextafter是constexpr,但目前只有一些编译器支持。GCC 确实通过它进行恒定传播,但 clang 不能(Godbolt)。0x1.fffffffffffffp-1;如果您希望它与 IEEE754 二进制 64系统中的文字常量一样快(启用优化)double,则在某些编译器上您将不得不等待 C++23 支持的该部分。(很可能一旦编译器能够做到这一点,比如 GCC,即使没有实际使用,它们也会进行优化-std=c++23。)
const double DoubleBelowOne = std::nextafter(1.0, 0.);在全局范围内,最坏的情况是在启动时运行该函数一次,从而在使用它的地方击败常量传播,但在与其他运行时变量一起使用时,其性能与 FP 文字常量大致相同。
利用C标准中规定的浮点表示的特性,可以在不调用函数的情况下进行计算。由于epsilon提供了略高于 1 的可表示数字之间的距离,并radix提供了用于表示数字的基数,因此略低于 1 的可表示数字之间的距离epsilon除以该基数:
#include <iostream>
#include <limits>
int main(void)
{
typedef float Float;
std::cout << std::hexfloat <<
1 - std::numeric_limits<Float>::epsilon() / std::numeric_limits<Float>::radix
<< '\n';
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2200 次 |
| 最近记录: |