简体   繁体   English

在C ++中是否有一个浮点文字后缀来使数字加倍精度?

[英]Is there a floating point literal suffix in C++ to make a number double precision?

I'm currently working on a C++ project which does numerical calculations. 我目前正在研究一个进行数值计算的C ++项目。 The vast, vast majority of the code uses single precision floating point values and works perfectly fine with that. 绝大多数代码使用单精度浮点值,并且完全可以正常工作。 Because of this I use compiler flags to make basic floating point literals single precision instead of the double precision, which is the default. 因此,我使用编译器标志来使基本浮点文字单精度而不是双精度,这是默认值。 I find that this makes expressions easier to read and I don't have to worry about forgetting a 'f' somewhere. 我发现这使得表达式更容易阅读,我不必担心在某个地方忘记'f'。 However, every now and then I need the extra precision offered by double precision calculations and my question is how I can get a double precision literal into such an expression. 但是,我时不时地需要双精度计算提供的额外精度,我的问题是如何将双精度文字输入到这样的表达式中。 Every way I've tried so far first store the value in a single precision variable and the converts the truncated value to a double precision value. 到目前为止,我尝试的每种方法都首先将值存储在单个精度变量中,并将截断值转换为双精度值。 Not what I want. 不是我想要的。

Some ways I've tried so far is given below. 我到目前为止尝试过的一些方法如下。

#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;
}

A run with single precision constants give the following results. 具有单精度常量的运行会产生以下结果。

~/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

It is my understanding that the 8 bytes provided by the last two cases should be enough to hold 1.0E200, a theory supported by the following output, where the same program is compiled without -fsingle-precision-constant. 据我所知,最后两种情况提供的8个字节应该足以容纳1.0E200,这是一个由以下输出支持的理论,其中相同的程序是在没有-fsingle-precision-constant的情况下编译的。

~/path$ g++ test.cpp  && ./a.out
8
1e+200
16
1e+200
8
1e+200
8
1e+200

A possible workaround suggested by the above examples is to use quadruple precision floating point literals everywhere I originally intended to use double precision, and cast to double precision whenever required by libraries and such. 上面示例建议的一种可能的解决方法是在我最初打算使用双精度的地方使用四倍精度浮点文字,并在库等需要时转换为双精度。 However, this feels a bit wasteful. 但是,这感觉有点浪费。

What else can I do? 我还可以做些什么?

Like Mark said, the standard says that its a double unless its followed by an f. 就像马克所说的那样,标准说它是一个双倍,除非它后跟一个f。

There are good reasons behind the standard and using compiler flags to get around it for convenience is bad practice. 标准背后有充分的理由,并且为方便起见,使用编译器标志绕过它是不好的做法。

So, the correct approach would be: 所以,正确的方法是:

  1. Remove the compiler flag 删除编译器标志
  2. Fix all the warnings about loss of precision when storing double values in floating point variables (add in all the f suffixes) 修复在浮点变量中存储double值时所有关于精度损失的警告(添加所有f后缀)
  3. When you need double, omit the f suffix. 当你需要double时,省略f后缀。

Its probably not the answer you were looking for, but it is the approach you should use if you care about the longevity of your code base. 它可能不是您正在寻找的答案,但如果您关心代码库的使用寿命,这是您应该使用的方法。

If you read 2.13.3/1 you'll see: 如果您阅读2.13.3 / 1,您会看到:

The type of a floating literal is double unless explicitly specified by a suffix. 除非后缀明确指定,否则浮动文字的类型为double。 The suffixes f and F specify float, the suffixes l and L specify long double. 后缀f和F指定float,后缀l和L指定long double。

In other words there is no suffix to specify double for a literal floating point constant if you change the default to float . 换句话说,如果将默认值更改为float ,则没有后缀为文字浮点常量指定double Unfortunately you can't have the best of both worlds in this case. 不幸的是,在这种情况下,你不可能拥有两全其美的优势。

If you can afford GCC 4.7 or Clang 3.1, use a user-defined literal: 如果你能负担得起GCC 4.7或Clang 3.1,请使用用户定义的文字:

double operator "" _d(long double v) { return v; }

Usage: 用法:

std::cout << sizeof(1.0E200_d) << std::endl;
std::cout << 1.0E200_d << std::endl;

Result: 结果:

8
1e+200

You can't define your own suffix, but maybe a macro like 你不能定义自己的后缀,但可能是宏

#define D(x) (double(x##L))

would work for you. 会对你有用。 The compiler ought to just emit a double constant, and appears to with -O2 on my system. 编译器应该只发出一个双常量,并且在我的系统上看起来是-O2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM