42

几年前,我学到了关于浮点数精度问题的艰难方法,所以我放弃了使用它们。但是,我仍然会遇到使用浮点数的代码,这让我感到畏缩,因为我知道有些计算会不准确。

那么,什么时候适合使用浮点数呢?

编辑: 作为信息,我不认为我遇到过一个数字的准确性并不重要的程序。但我有兴趣听听例子。

4

7 回答 7

59

简短的回答:只有当你确切地知道你在做什么以及为什么时,你才需要使用浮点数。

长答案:据我所知,浮点数(而不是doubles)在 3D API 之外不再真正使用。浮点数和双精度数在现代 CPU 上具有相同的性能特征,双精度数更大一些,仅此而已。如果有疑问,请使用双精度。

哦,是的,当然,使用小数进行财务计算。

于 2009-01-02T20:53:36.090 回答
12

在一般情况下,所有浮点计算都是不准确的,浮点数比双精度数还要多。如果您想了解更多信息,请阅读 每个计算机科学家应该了解的关于浮点运算的知识

至于何时使用浮点数——通常在精度不如节省内存重要时使用。例如视频游戏中的简单粒子模拟。

于 2009-01-02T20:53:51.910 回答
9

首先,如果您想精确表示十进制值,切勿使用浮点数或双精度数 - 使用整数类型(int、long 等)或小数(它只是具有比例因子的整数类型)。浮点数和双精度数在内部转换为以 2 为底的指数表示,而以 10 为底的指数表示精确表示的数字通常不能精确表示。(例如,数字 10 仅由浮点数或双精度数近似表示)。

其次,就精度而言,这取决于您的需求。我不同意你的观点,即从来没有计算精度无关紧要。您通常有一个特定的需求,即您的最终结果准确地说是 3 位数。如果您的输入只有有限的准确度,那么寻找可能的最高精度是没有意义的 - 比如说您称重约 5 克面粉,而您的秤的准确度只有 0.5 克。也就是说,中间计算通常受益于更高的精度,但如果经常速度的话,这比高精度更重要。

第三,在执行一系列计算时,比如在一个循环中,你需要知道在处理任何不精确的计算时你在做什么——你会产生四舍五入的错误,一些算法可能无法达到任何精确度的答案. 详细了解这些问题可能需要一门数值分析课程。这不取决于您为计算选择浮点数还是双精度数。

对于浮点计算,我通常会使用双精度数,因为它们比浮点数更通用、更快。但是,浮点数更小,如果您需要存储大量浮点数,则可以选择它们来防止由于缓存未命中而导致的性能问题。

据我所知,硬件支持双精度浮点处理,但浮点数不支持浮点处理,因此使用浮点数会导致转换为双精度。但是,在传递浮点数时迭代计算值时,某些例程会更快停止,因为这意味着您只需要大约 8 位精度,而双精度大约需要 16 位。

于 2009-01-03T15:09:20.043 回答
7

在很多情况下,您会想要使用float. 然而,我不明白的是你可以使用什么。如果您的意思是使用double而不是float,那么是的,在大多数情况下,您想要这样做。但是,double也会有精度问题。decimal只要准确性很重要,您就应该使用它。

float并且double在许多应用中非常有用。decimal是一种昂贵的数据类型,它的范围(它可以表示的最大数的大小)小于double. 计算机通常对这些数据类型具有特殊的硬件级别支持。它们在科学计算中被大量使用。基本上,它们是您要使用的主要小数数据类型。然而,在精确度极其重要的货币计算中,这是可行decimal的方法。

于 2009-01-02T20:50:10.840 回答
6

我能想到的最常见的原因是节省空间。并不是说这通常值得担心,但在某些情况下它很重要。float 占用的内存是 double 的一半,因此您可以在同一空间中获得两倍的内存。例如,我有一个数字数组,它太大而不能作为双精度数放入 RAM,但适合作为浮点数。

于 2009-01-02T21:09:08.523 回答
5

事实上,使用 32 位浮点数(即“单精度”)仍然很常见:图形应用程序和打印。

另一个原因是带有 GPU 的显卡。数据类型越小,操作越快,因为必须传输的位越少。整数数据类型在高动态范围图像方面存在问题:眼睛能够在 1: 10^13 的亮度范围内工作,并且可以识别 ca。4000级。因此,虽然整数数据类型可以存储级别数,但它们无法存储背景亮度,而浮点数则没有问题。事实上,IEEE 754R 允许使用 16 位和 10 位尾数的新“半精度”浮点数,这会损失一些精度,但会允许更快的速度。OpenGL 和 DirectX 例如广泛使用浮点数。眼睛对伪影非常宽容,所以那里没有问题。

所有其他基于图形的媒体都继承了浮动作为方便的措施。尾数有 24 位,因此允许 2^24 = 16,7 百万个连续步骤。如果您有一台分辨率为 2000 dpi 的打印机,您仍然可以打印 213x213 米的纸张。精度绰绰有余。

于 2009-02-20T17:45:15.753 回答
3

使用 float 来表示性能和大小。如果您可以管理精度损失。

虽然现代处理器确实需要相同的时间来处理单精度和双精度操作,但如果使用带有 SIMD(x86 上的 MMX/SSE/等)指令的浮点数,有时可以获得两倍的吞吐量。

SSE 寄存器为 128 位宽,可容纳4 个浮点数2 个双精度数。因此,如果使用得当,您可以使用浮点数执行两倍于双精度数的操作。

在处理非常大的数据集时,减小大小(4 个字节而不是 8 个字节)变得很重要(并且由于缓存等原因,减小大小通常也会提高性能)

于 2009-01-03T07:41:52.023 回答