我读过关于双精度和单精度之间的区别。然而,在大多数情况下,float和double似乎是可互换的,即使用其中一个似乎不会影响结果。事实真的如此吗?什么时候浮点数和双精度数可以互换?它们之间有什么区别?
当前回答
float类型,长度为32位,精度为7位。虽然它可以存储非常大或非常小的范围(+/- 3.4 * 10^38或* 10^-38)的值,但它只有7位有效数字。
类型double, 64位长,具有更大的范围(*10^+/-308)和15位精度。
类型long double名义上是80位,尽管给定的编译器/操作系统配对可能会将其存储为12-16字节以进行对齐。长双精度数的指数大得离谱,应该有19位精度。微软以其无限的智慧,将long double限制为8字节,与普通double相同。
一般来说,当需要浮点值/变量时,只需使用double类型。默认情况下,表达式中使用的字面浮点值将被视为双精度值,并且大多数返回浮点值的数学函数都会返回双精度值。如果只使用double,就可以省去很多麻烦和类型转换。
其他回答
给定二次方程:x2−4.0000000 x + 3.9999999 = 0, 10位有效数字的精确根为:r1 = 2.000316228, r2 = 1.999683772。
使用float和double,我们可以编写一个测试程序:
#include <stdio.h>
#include <math.h>
void dbl_solve(double a, double b, double c)
{
double d = b*b - 4.0*a*c;
double sd = sqrt(d);
double r1 = (-b + sd) / (2.0*a);
double r2 = (-b - sd) / (2.0*a);
printf("%.5f\t%.5f\n", r1, r2);
}
void flt_solve(float a, float b, float c)
{
float d = b*b - 4.0f*a*c;
float sd = sqrtf(d);
float r1 = (-b + sd) / (2.0f*a);
float r2 = (-b - sd) / (2.0f*a);
printf("%.5f\t%.5f\n", r1, r2);
}
int main(void)
{
float fa = 1.0f;
float fb = -4.0000000f;
float fc = 3.9999999f;
double da = 1.0;
double db = -4.0000000;
double dc = 3.9999999;
flt_solve(fa, fb, fc);
dbl_solve(da, db, dc);
return 0;
}
运行程序得到:
2.00000 2.00000
2.00032 1.99968
注意,这些数字并不大,但是使用float仍然可以得到抵消效果。
(事实上,上面的方法并不是用单精度浮点数或双精度浮点数求解二次方程的最佳方法,但即使使用更稳定的方法,答案也不会改变。)
与整型(整数)不同,浮点数有小数点,双精度浮点数也有。 但两者之间的区别在于,double类型的细节是float类型的两倍,这意味着它的小数点后的数字可以是小数点后的两倍。
双精度为64,单精度为64 (float)是32位。 double有一个更大的尾数(实数的整数位)。 任何不准确的地方都将在double中减小。
巨大的差异。
顾名思义,double的精度是浮点数[1]的2倍。一般来说,double有15个十进制数字的精度,而float有7个。
下面是如何计算位数的:
Double有52个尾数位+ 1个隐藏位:log(253)÷log(10) = 15.95位 浮点数有23个尾数位+ 1个隐藏位:log(224)÷log(10) = 7.22位数字
当重复计算时,这种精度损失可能导致更大的截断误差累积。
float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.7g\n", b); // prints 9.000023
而
double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
b += a;
printf("%.15g\n", b); // prints 8.99999999999996
同样,float的最大值约为3e38,但double约为1.7e308,因此对于一些简单的事情,使用float可以比double更容易达到“无穷大”(即一个特殊的浮点数),例如计算60的阶乘。
在测试期间,可能有一些测试用例包含这些巨大的数字,如果使用浮点数,可能会导致程序失败。
当然,有时,即使是双精度也不够精确,因此我们有时会有长双精度[1](上面的例子在Mac上给出了9.000000000000000066),但所有浮点类型都有四舍五入错误,所以如果精度非常重要(例如货币处理),你应该使用int或分数类。
此外,不要使用+=对大量浮点数求和,因为错误很快就会累积起来。如果使用Python,请使用fsum。否则,尝试实现Kahan求和算法。
[1]: C和c++标准没有指定float、double和long double的表示方式。这三种方法都有可能实现为IEEE双精度。然而,对于大多数架构(gcc, MSVC;x86, x64, ARM) float确实是IEEE单精度浮点数(binary32), double是IEEE双精度浮点数(binary64)。
浮点数的精度比双精度数低。虽然你已经知道了,但为了更好地理解,请阅读《关于浮点算术我们应该知道什么》。
推荐文章
- 什么是“参数依赖查找”(又名ADL,或“Koenig查找”)?
- 公共朋友交换成员函数
- 如何将文件指针(file * fp)转换为文件描述符(int fd)?
- 如何在Go中使用c++
- 自定义c++分配器的引人注目的例子?
- RAII和c++中的智能指针
- 如何构建和使用谷歌TensorFlow c++ api
- C“int”的大小是2字节还是4字节?
- 多维数组如何在内存中格式化?
- printf()和puts()在C语言中的区别是什么?
- 断言是邪恶的吗?
- 下面这些短语在c++中是什么意思:0 -,default-和value-initialization?
- 在STL地图中,使用map::insert比[]更好吗?
- C++ Linux的想法?
- 有效,但毫无价值的语法在开关情况下?