C++ float和double的区别是什么?

C++ float和double的区别是什么?,c++,c,floating-point,precision,C++,C,Floating Point,Precision,我读过关于双精度和单精度的区别。然而,在大多数情况下,float和double似乎可以互换,即使用其中一种似乎不会影响结果。真的是这样吗?浮子和双浮子什么时候可以互换?它们之间有什么区别? 双精度是64,单精度 (浮点)是32位 double具有更大的尾数(实数的整数位) 任何误差都将在双精度模式下减小 浮点数的精度低于双精度浮点数。尽管您已经知道,但请阅读以便更好地理解。以下是标准C99(ISO-IEC 9899 6.2.5§10)或C++2003(ISO-IEC 14882-2003 3.1

我读过关于双精度和单精度的区别。然而,在大多数情况下,
float
double
似乎可以互换,即使用其中一种似乎不会影响结果。真的是这样吗?浮子和双浮子什么时候可以互换?它们之间有什么区别?

  • 双精度是64,单精度 (浮点)是32位
  • double具有更大的尾数(实数的整数位)
  • 任何误差都将在双精度模式下减小

浮点数的精度低于双精度浮点数。尽管您已经知道,但请阅读以便更好地理解。

以下是标准C99(ISO-IEC 9899 6.2.5§10)或C++2003(ISO-IEC 14882-2003 3.1.9§8)标准的内容:


有三种浮点类型:
float
double
long double
。类型
double
提供的精度至少与
float
相同,类型
long double
提供的精度至少与
double
相同。
float
类型的值集是
double
类型的值集的子集;
double
类型的值集是
long double
类型的值集的子集

C++标准添加:

浮点类型的值表示由实现定义


我建议看一看深入介绍IEEE浮点标准的优秀文章。您将了解表示的详细信息,并将意识到在大小和精度之间存在权衡。浮点表示的精度随着大小的减小而增加,因此-1和1之间的浮点数是精度最高的。

使用浮点数时,您不能相信您的本地测试将与在服务器端执行的测试完全相同。本地系统上的环境和编译器可能不同,最终测试在哪里运行。我以前在一些TopCoder竞赛中多次看到过这个问题,特别是当你试图比较两个浮点数时。

浮点计算中涉及的数字大小不是最相关的。相关的是正在进行的计算

#include <iostream>
#include <iomanip>

int main(){
  for(float t=0;t<1;t+=0.01){
     std::cout << std::fixed << std::setprecision(6) << t << std::endl;
  }
}
本质上,如果您正在执行一个计算,并且结果是一个无理数或循环小数,那么当该数字被压缩到您正在使用的有限大小数据结构中时,将出现舍入错误。由于double是float大小的两倍,因此舍入误差将小得多

测试可能特别使用会导致此类错误的数字,因此测试表明您在代码中使用了适当的类型。

巨大的差异

顾名思义,a的精度是[1]的2倍。通常,
double
的精度为15位小数,而
float
的精度为7位

以下是计算位数的方法:

double
有52个尾数位+1个隐藏位:log(253)÷log(10)=15.95位

float
有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
float a=1.f/81;
浮动b=0;
对于(int i=0;i<729;++i)
b+=a;
printf(“%.7g\n”,b);//打印9.000023

双a=1.0/81;
双b=0;
对于(int i=0;i<729;++i)
b+=a;
printf(“%.15g\n”,b);//打印8.9999999996
此外,浮点的最大值约为
3e38
,而double约为
1.7e308
,因此使用
float
double
更容易达到“无穷大”(即一个特殊的浮点数),例如计算60的阶乘

在测试过程中,可能有一些测试用例包含这些巨大的数字,如果使用浮点,可能会导致程序失败


当然,有时,即使是
double
也不够精确,因此我们有时会使用
长double
[1](上面的示例在Mac上给出了9.000000000000000066),但所有浮点类型都会出现舍入错误,因此如果精度非常重要(例如,货币处理)您应该使用
int
或分数类


此外,不要使用
+=
对大量浮点数求和,因为错误积累得很快。如果您使用的是Python,请使用
fsum
。否则,请尝试实现



(1):C和C++标准没有指定“代码>浮标< /代码>、<代码>双和 long double < /C>。有可能所有三个都实现为IEEE双精度。然而,对于大多数体系结构(gcc、MSVC;x86、x64、ARM)

float
实际上是IEEE单精度浮点数(binary32),
double
是IEEE双精度浮点数(binary64)。

给定一个二次方程: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;
}  
请注意,数字不是很大,但仍然可以使用
float
获得取消效果


(事实上,上述不是使用单精度或双精度浮点数求解二次方程的最佳方法,但即使使用a,答案也不会改变。)

类型浮点,32位长,精度为7位。虽然它可以存储范围非常大或非常小的值(+/-3.4*10^38或*10^-38),但它只有7个有效数字

类型double,64位长,具有更大的范围(*10^+/-
2.00000 2.00000
2.00032 1.99968
#include <iostream>
#include <iomanip>

int main(){
  for(float t=0;t<1;t+=0.01){
     std::cout << std::fixed << std::setprecision(6) << t << std::endl;
  }
}
0.000000
0.010000
0.020000
0.030000
0.040000
0.050000
0.060000
0.070000
0.080000
0.090000
0.100000
0.110000
0.120000
0.130000
0.140000
0.150000
0.160000
0.170000
0.180000
0.190000
0.200000
0.210000
0.220000
0.230000
0.240000
0.250000
0.260000
0.270000
0.280000
0.290000
0.300000
0.310000
0.320000
0.330000
0.340000
0.350000
0.360000
0.370000
0.380000
0.390000
0.400000
0.410000
0.420000
0.430000
0.440000
0.450000
0.460000
0.470000
0.480000
0.490000
0.500000
0.510000
0.520000
0.530000
0.540000
0.550000
0.560000
0.570000
0.580000
0.590000
0.600000
0.610000
0.620000
0.630000
0.640000
0.650000
0.660000
0.670000
0.680000
0.690000
0.700000
0.710000
0.720000
0.730000
0.740000
0.750000
0.760000
0.770000
0.780000
0.790000
0.800000
0.810000
0.820000
0.830000
0.839999
0.849999
0.859999
0.869999
0.879999
0.889999
0.899999
0.909999
0.919999
0.929999
0.939999
0.949999
0.959999
0.969999
0.979999
0.989999
0.999999