float和double有什么区别?

我读过有关双精度和单精度之间的区别。 但是,在大多数情况下, floatdouble似乎是可以互换的,即使用其中一个或另一个似乎不会影响结果。 这是真的吗? 浮动和双打何时可以互换? 他们之间有什么不同?


巨大的差异。

顾名思义, double精度float的精度是2x [1]。 通常, 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("%.7gn", b); // prints 9.000023

double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
    b += a;
printf("%.15gn", b); // prints 8.99999999999996

此外,浮动的最大值约为3e38 ,但双约为1.7e308 ,因此使用float可以打“无限”(即一个特殊的浮点数)比更容易double简单的东西,如计算的60阶乘。

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


当然,有时甚至double也不够准确,所以我们有时候会有long double [1](上面的例子给出了Mac上的9.000000000000000066),但是所有浮点类型都有舍入误差,所以如果精度非常重要(如货币处理),你应该使用int或分数类。


此外,不要使用+=来对大量的浮点数进行求和,因为错误会很快积累。 如果您使用Python,请使用fsum 。 否则,尝试实施Kahan求和算法。


[1]:C和C ++标准没有指定floatdoublelong double 。 有可能所有三个实现为IEEE双精度。 尽管如此,对于大多数体系结构(gcc,MSVC; x86,x64,ARM), float的确是IEEE单精度浮点数(binary32), double是IEEE双精度浮点数(binary64)。


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

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

C ++标准增加了:

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

我建议看一下每位计算机科学家应该了解的有关浮点运算的优秀内容,其中深入讨论了IEEE浮点标准。 您将了解代表性细节,并且您会意识到在幅度和精度之间存在权衡。 浮点数表示的精度随着数值的减小而增加,因此浮点数在-1和1之间是精度最高的浮点数。


给定一个二次方程:x2 - 4.0000000 x + 3.9999999 = 0,到10个有效数字的确切根是r1 = 2.000316228和r2 = 1.999683772。

使用floatdouble ,我们可以编写一个测试程序:

#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("%.5ft%.5fn", 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("%.5ft%.5fn", 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获取取消效果。

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

链接地址: http://www.djcxy.com/p/2217.html

上一篇: What is the difference between float and double?

下一篇: Difference between private, public, and protected inheritance