我看到另一个人的.c文件中有这个:
const float c = 0.70710678118654752440084436210485f;
他想避免计算sqrt(1/2)
,这与IT技术有关。
这是否真的可以使用纯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个小数位,如此处所述:
float has 24 binary bits of precision, and double has 53.
我希望最后的输出结果与倒数第二个输出结果相同,即f
后缀不会阻止数字变成double
类型。我认为当我写下这段代码时:
const double df = 0.70710678118654752440084436210485f;
发生的情况是,首先将数字变成一个
float
,然后存储为一个 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.
[编辑]
关于__float128
,它不是标准的,因此已经退出了竞争。更多信息请参见这里。
long double
。 - Some programmer dudesqrt(1/2)
,无论如何都会失去精度!!! - barak manoslong double
,它是扩展双精度
(80到96位宽)的。 - 0xF1