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


当前回答

内置比较操作的不同之处在于,当你用浮点数比较两个数字时,数据类型的差异(即浮点数或双精度数)可能会导致不同的结果。

其他回答

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

给定二次方程: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大小的两倍,所以舍入误差会小很多。

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

与整型(整数)不同,浮点数有小数点,双精度浮点数也有。 但两者之间的区别在于,double类型的细节是float类型的两倍,这意味着它的小数点后的数字可以是小数点后的两倍。

我刚刚遇到了一个错误,我花了很长时间才弄清楚,这可能会给你一个浮点精度的好例子。

#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

正如你所看到的,在0.83之后,精度显著下降。

然而,如果我将t设为双倍,这样的问题就不会发生。

我花了五个小时才意识到这个小错误,它毁了我的程序。