C++中是否有一个浮点文字后缀来使数字的精度翻倍
Is there a floating point literal suffix in C++ to make a number double precision?
我目前正在进行一个进行数值计算的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;
}
使用单精度常量运行会得到以下结果。
~/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
我的理解是,最后两种情况提供的8个字节应该足以容纳1.0E200,这一理论得到了以下输出的支持,其中编译相同的程序时没有-fsingle精度常数。
~/path$ g++ test.cpp && ./a.out
8
1e+200
16
1e+200
8
1e+200
8
1e+200
上面的例子建议的一个可能的解决方法是,在我最初打算使用双精度的地方使用四重精度浮点文字,并在库等需要时强制转换为双精度。然而,这感觉有点浪费。
我还能做什么?
就像Mark所说的,标准说它是双精度的,除非后面跟着f。
这个标准背后有充分的理由,使用编译器标志来绕过它是不好的做法。
因此,正确的方法是:
- 删除编译器标志
- 修复在浮点变量中存储双值时丢失精度的所有警告(添加所有f后缀)
- 当您需要双精度时,请省略f后缀
这可能不是你想要的答案,但如果你关心代码库的寿命,这是你应该使用的方法。
如果您阅读2.13.3/1,您将看到:
除非明确指定,否则浮动文字的类型为双精度通过后缀。后缀f和f指定float,后缀l和l指定长双精度。
换句话说,如果将默认值更改为float
,则没有后缀可以为文字浮点常量指定double
。不幸的是,在这种情况下,你不可能两全其美。
如果您能负担得起GCC 4.7或Clang 3.1,请使用用户定义的文字:
double operator "" _d(long double v) { return v; }
用法:
std::cout << sizeof(1.0E200_d) << std::endl;
std::cout << 1.0E200_d << std::endl;
结果:
8
1e+200
您不能定义自己的后缀,但可能是像这样的宏
#define D(x) (double(x##L))
会为你工作。编译器应该只发出一个双常量,并且在我的系统上显示为-O2
。
- 当使用比格式支持的精度更高的精度来显示数字时,会写出什么数据
- 为什么将双精度转换为 int 似乎在第 16 位数字之后将其四舍五入?
- 使用浮点数和双精度数的非常小数字的数学
- 使用设置精度时如何阻止数字向上舍入?
- 如何将数字输出到文件中,所有数字都具有相同的精度
- 如何在 c++ 中添加两个大的双精度数字
- 字符串和双精度的麻烦,等值后再得到一个数字
- 数字小于机器精度的安全算术?
- 避免双精度数字的四舍五入
- 有没有办法将数字作为字符串,并在不使用浮点数或双精度数的情况下将其四舍五入到确切的位数
- 将协议缓冲区中的二进制双精度数组转换为 JavaScript 数字
- 2 个给定数字之间的双精度密度
- 如何将精度设置为C 的100位数字
- 如何在不丢失第一位数字的情况下打印出双精度值
- 试图回合数字时如何避免丧失精度?(C )
- 双精度数字程序意外值
- 在小数点之前设置数字的精度
- 如何将精度设置为一个数字
- 如何存储具有一定精度的数字
- 如何使用boost::multiprecision在运行时更改数字精度