32位十进制数的浮点/双精度分析

gsa*_*ras 3 c c++ precision

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

const float c = 0.70710678118654752440084436210485f;
Run Code Online (Sandbox Code Playgroud)

他想避免计算的地方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;
Run Code Online (Sandbox Code Playgroud)

输出是这样的:

                   *       ** ***
                   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
Run Code Online (Sandbox Code Playgroud)

哪个*是最后一个准确数字float,**最后一个准确数字double***最后一个准确数字long double.

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

float输出有24个,如预期,如说在这里:

float has 24 binary bits of precision, and double has 53.
Run Code Online (Sandbox Code Playgroud)

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

const double df = 0.70710678118654752440084436210485f;
Run Code Online (Sandbox Code Playgroud)

会发生的是,首先数字变为float1,然后存储为a double,所以在第24个十进制数字之后,它有零,这就是为什么double精度停在那里.

我对么?

这个答案我发现了一些相关的信息:

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.
Run Code Online (Sandbox Code Playgroud)

[编辑]

关于__float128,它不是标准的,因此它不在竞争中.在这里查看更多.

Mat*_*att 5

从标准:

有三种浮点类型:float,double和long double.double类型提供至少与float一样多的精度,long double类型提供至少与double一样多的精度.float类型的值集是double类型的值集的子集; double类型的值集是long double类型的值集的子集.浮点类型的值表示是实现定义的.

所以你可以在这个问题上看到你的问题:标准实际上没有说明精确浮点数是多少.

在标准实现方面,您需要查看IEEE754,这意味着Irineau和Davidmh的另外两个答案是解决问题的完美有效方法.

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

除非由su ffi x明确指定,否则浮动文字的类型是双重的.su ffi xes f和F指定float,su ffi xes l和L指定long double.

因此,除非使用后缀,否则创建long double遗嘱的尝试与double分配给它的文字具有相同的精度L.

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

最后要注意的是:由于精度没有明确定义,为什么不能获得比它需要的更长的常数?似乎总是定义一个足够精确的常量,以便始终可以表示,而不管类型如何.