use*_*052 17 c++ precision gcc literals
我目前正在研究一个进行数值计算的C++项目.绝大多数代码使用单精度浮点值,并且完全可以正常工作.因此,我使用编译器标志来使基本浮点文字单精度而不是双精度,这是默认值.我发现这使得表达式更容易阅读,我不必担心在某个地方忘记'f'.但是,我时不时地需要双精度计算提供的额外精度,我的问题是如何将双精度文字输入到这样的表达式中.到目前为止,我尝试的每种方法都首先将值存储在单个精度变量中,并将截断值转换为双精度值.不是我想要的.
我到目前为止尝试过的一些方法如下.
#include <iostream>
int main()
{
std::cout << sizeof(1.0E200) << std::endl;
std::cout << 1.0E200 << std::endl;
std::cout << sizeof(1.0E200L) << std::endl;
std::cout << 1.0E200L << std::endl;
std::cout << sizeof(double(1.0E200)) << std::endl;
std::cout << double(1.0E200) << std::endl;
std::cout << sizeof(static_cast<double>(1.0E200)) << std::endl;
std::cout << static_cast<double>(1.0E200) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
具有单精度常量的运行会产生以下结果.
~/path$ g++ test.cpp -fsingle-precision-constant && ./a.out
test.cpp:6:3: warning: floating constant exceeds range of ‘float’ [-Woverflow]
test.cpp:7:3: warning: floating constant exceeds range of ‘float’ [-Woverflow]
test.cpp:12:3: warning: floating constant exceeds range of ‘float’ [-Woverflow]
test.cpp:13:3: warning: floating constant exceeds range of ‘float’ [-Woverflow]
test.cpp:15:3: warning: floating constant exceeds range of ‘float’ [-Woverflow]
test.cpp:16:3: warning: floating constant exceeds range of ‘float’ [-Woverflow]
4
inf
16
1e+200
8
inf
8
inf
Run Code Online (Sandbox Code Playgroud)
据我所知,最后两种情况提供的8个字节应该足以容纳1.0E200,这是一个由以下输出支持的理论,其中相同的程序是在没有-fsingle-precision-constant的情况下编译的.
~/path$ g++ test.cpp && ./a.out
8
1e+200
16
1e+200
8
1e+200
8
1e+200
Run Code Online (Sandbox Code Playgroud)
上面示例建议的一种可能的解决方法是在我最初打算使用双精度的地方使用四倍精度浮点文字,并在库等需要时转换为双精度.但是,这感觉有点浪费.
我还可以做些什么?
Car*_*arl 19
就像马克所说的那样,标准说它是一个双倍,除非它后跟一个f.
标准背后有充分的理由,并且为方便起见,使用编译器标志绕过它是不好的做法.
所以,正确的方法是:
它可能不是您正在寻找的答案,但如果您关心代码库的使用寿命,这是您应该使用的方法.
Mar*_*k B 11
如果您阅读2.13.3/1,您会看到:
除非后缀明确指定,否则浮动文字的类型为double.后缀f和F指定float,后缀l和L指定long double.
换句话说,double如果将默认值更改为,则没有为文字浮点常量指定的后缀float.不幸的是,在这种情况下,你不可能拥有两全其美的优势.
如果你能负担得起GCC 4.7或Clang 3.1,请使用用户定义的文字:
double operator "" _d(long double v) { return v; }
Run Code Online (Sandbox Code Playgroud)
用法:
std::cout << sizeof(1.0E200_d) << std::endl;
std::cout << 1.0E200_d << std::endl;
Run Code Online (Sandbox Code Playgroud)
结果:
8
1e+200
Run Code Online (Sandbox Code Playgroud)
你不能定义自己的后缀,但可能是宏
#define D(x) (double(x##L))
Run Code Online (Sandbox Code Playgroud)
会对你有用.编译器应该只发出一个双常数,并且-O2在我的系统上显示.