我读过关于双精度和单精度之间的区别。然而,在大多数情况下,float和double似乎是可互换的,即使用其中一个似乎不会影响结果。事实真的如此吗?什么时候浮点数和双精度数可以互换?它们之间有什么区别?
当前回答
双精度为64,单精度为64 (float)是32位。 double有一个更大的尾数(实数的整数位)。 任何不准确的地方都将在double中减小。
其他回答
浮点计算中涉及的数字的大小并不是最相关的事情。相关的是正在进行的计算。
从本质上讲,如果您正在执行计算,而结果是一个无理数或循环小数,那么当将该数字压缩到您正在使用的有限大小的数据结构中时,将会出现舍入错误。因为double是float大小的两倍,所以舍入误差会小很多。
测试可能特别使用可能导致这种错误的数字,因此测试您是否在代码中使用了适当的类型。
内置比较操作的不同之处在于,当你用浮点数比较两个数字时,数据类型的差异(即浮点数或双精度数)可能会导致不同的结果。
巨大的差异。
顾名思义,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)。
以下是标准C99 (ISO-IEC 9899 6.2.5§10)或c++ 2003 (ISO-IEC 14882-2003 3.1.9§8)标准所说的:
浮点数有三种类型:浮点数、双精度浮点数和长双精度浮点数。double类型提供的精度至少与float类型相同,long double类型提供的精度至少与double类型相同。float类型的值集是double类型值集的子集;double类型的值集是long double类型值集的子集。
c++标准增加了:
浮点类型的值表示是由实现定义的。
我建议你看一看优秀的《每个计算机科学家都应该知道浮点算术》,它深入介绍了IEEE浮点标准。您将了解表示细节,并将意识到在量级和精度之间存在权衡。浮点表示的精度随着幅度的减小而增加,因此-1到1之间的浮点数具有最高的精度。
双精度为64,单精度为64 (float)是32位。 double有一个更大的尾数(实数的整数位)。 任何不准确的地方都将在double中减小。