c++ - 32位小数浮点/ double 解析

标签 c++ c precision

从另一个人的 .c 文件中,我看到了这个:

const float c = 0.70710678118654752440084436210485f;

他想避免 sqrt(1/2) 的计算。

这真的可以用普通的 C/C++ 以某种方式存储吗?我的意思是不失去精度。这对我来说似乎是不可能的。

我正在使用 C++,但我不认为这两种语言之间的精度差异太大(如果有的话),这就是我没有测试它的原因。

所以,我写了这几行,看看代码的行为:

std::cout << "Number:    0.70710678118654752440084436210485\n";

const float f = 0.70710678118654752440084436210485f;
std::cout << "float:     " << std::setprecision(32) << f << std::endl;

const double d = 0.70710678118654752440084436210485; // no f extension
std::cout << "double:    " << std::setprecision(32) << d << std::endl;

const double df = 0.70710678118654752440084436210485f;
std::cout << "doublef:   " << std::setprecision(32) << df << std::endl;

const long double ld = 0.70710678118654752440084436210485;
std::cout << "l double:  " << std::setprecision(32) << ld << std::endl;

const long double ldl = 0.70710678118654752440084436210485l; // l suffix!
std::cout << "l doublel: " << std::setprecision(32) << ldl << std::endl;

输出是这样的:

                   *       ** ***
                   v        v v
Number:    0.70710678118654752440084436210485    // 32 decimal digits
float:     0.707106769084930419921875            // 24 >>      >>
double:    0.70710678118654757273731092936941
doublef:   0.707106769084930419921875            // same as float
l double:  0.70710678118654757273731092936941    // same as double
l doublel: 0.70710678118654752438189403651592    // suffix l

其中*float的最后一个准确数字,**double的最后一个准确数字,并且*** long double 的最后一位准确数字。

double 的输出有 32 位十进制数字,因为我已将 std::cout 的精度设置为该值。

float 输出有 24,正如预期的那样,如 here :

float has 24 binary bits of precision, and double has 53.

我希望最后一个输出与前一个输出相同,即 f 后缀不会阻止数字变成 double。我认为当我写这篇文章时:

const double df = 0.70710678118654752440084436210485f;

首先数字变成了float,然后存储为double,所以在第 24 位十进制数字之后,它有零,这就是为什么 double 精度到此为止。

我说的对吗?

来自 this回答我找到了一些相关资料:

float x = 0 has an implicit typecast from int to float.
float x = 0.0f does not have such a typecast.
float x = 0.0 has an implicit typecast from double to float.

[编辑]

关于__float128,它不是标准的,因此它被排除在竞争之外。查看更多here .

最佳答案

来自标准:

There are three floating point types: float, double, and long double. The type double provides at least as much precision as float, and the type long double provides at least as much precision as double. The set of values of the type float is a subset of the set of values of the type double; the set of values of the type double is a subset of the set of values of the type long double. The value representation of floating-point types is implementation-defined.

所以您可以看到您对这个问题的看法:该标准实际上并没有说明 float 的精确度。

就标准实现而言,您需要查看 IEEE754,这意味着 Irineau 和 Davidmh 的其他两个答案是解决该问题的完全有效方法。

关于后缀字母表示类型,再看标准:

The type of a floating literal is double unless explicitly specified by a suffix. The suffixes f and F specify float, the suffixes l and L specify long double.

因此,除非您使用 L后缀。

我知道其中一些答案可能看起来并不令人满意,但在您拒绝答案之前,需要对相关标准进行大量背景阅读。这个答案已经比预期的要长,所以我不会在这里尝试解释所有内容。

最后要注意的是:既然精度没有明确定义,为什么不用一个比需要的更长的常量呢?似乎总是定义一个足够精确的常量是有意义的,无论类型如何,它总是可表示的。

关于c++ - 32位小数浮点/ double 解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23629126/

相关文章:

c++ - 在 C++ 中添加静态库时的意外行为

c++ - linux 上的链接问题(找不到合适的库的名称)

c++ - 为什么别名模板给出冲突的声明?

sql - Float 在数据库 Sql Server 中存储为 Real

java - 如何判断矩形是否是黄金矩形?

python - 用opencv提取最大的blob

c - 释放数据时内存泄漏?

c++ - 计算嵌入式C中代码块的时钟周期

c - 有效地从 CSV 中读取特定行,C

google-chrome - Google Chrome WebGL Shader编译链接器错误,统一名称相同但类型/精度不同