99

在 C++ 中使用一个而不是另一个的优点和缺点是什么?

4

11 回答 11

108

如果你想知道真正的答案,你应该阅读 每个计算机科学家应该知道的关于浮点运算的知识

简而言之,虽然它的表示double允许更高的精度,但对于某些计算,它会产生更大的误差。“正确”的选择是:使用尽可能多的精度,但不要更多,并选择正确的算法

无论如何,许多编译器都会在“非严格”模式下进行扩展浮点数学运算(即使用硬件中可用的更广泛的浮点类型,例如 80 位和 128 位浮点),这也应该被考虑在内。在实践中,您几乎看不出速度上有任何差异——无论如何它们都是硬件原生的。

于 2009-07-02T14:01:55.240 回答
48

除非您有特定的理由不这样做,否则请使用 double。

也许令人惊讶的是,C(和 C++)中“正常”的浮点类型是 double 而不是 float。sinlog等标准数学函数将双精度数作为参数,并返回双精度数。一个普通的浮点文字,就像你在你的程序中写3.14时一样,具有 double 类型。不浮动。

在典型的现代计算机上,双精度数可以与浮点数一样快,甚至更快,因此性能通常不是需要考虑的因素,即使对于大型计算也是如此。(这些必须是大型计算,否则性能甚至不应该进入你的脑海。我的新 i7 台式电脑可以在一秒钟内进行 60 亿次双倍乘法。)

于 2009-09-25T08:12:54.817 回答
27

这个问题无法回答,因为这个问题没有上下文。以下是一些可能会影响选择的因素:

  1. 浮点数、双精度数和长双精度数的编译器实现。C++ 标准规定:

    有三种浮点类型:float、double 和 long double。double 类型提供的精度至少与 float 一样,long double 类型提供的精度至少与 double 一样。

    所以,这三个在内存中可以是相同的大小。

  2. FPU 的存在。并非所有 CPU 都有 FPU,有时会模拟浮点类型,有时只是不支持浮点类型。

  3. FPU 架构。IA32 的 FPU 内部为 80 位 - 32 位和 64 位浮点数在加载时扩展为 80 位,并在存储时减少。还有 SIMD 可以并行执行四个 32 位浮点数或两个 64 位浮点数。标准中未定义 SIMD 的使用,因此需要编译器进行更复杂的分析以确定是否可以使用 SIMD,或者需要使用特殊函数(库或内部函数)。80 位内部格式的结果是,根据数据保存到 RAM 的频率,您可能会得到稍微不同的结果(因此会丢失精度)。出于这个原因,编译器不会特别好地优化浮点代码。

  4. 内存带宽。如果双精度型比浮点型需要更多存储空间,则读取数据需要更长的时间。这是天真的答案。在现代 IA32 上,这完全取决于数据的来源。如果它在 L1 缓存中,则负载可以忽略不计,前提是数据来自单个缓存行。如果它跨越多个缓存行,则开销很小。如果它来自 L2,则需要更长的时间,如果它在 RAM 中,则需要更长的时间,最后,如果它在磁盘上,则需要很长时间。所以浮点数或双精度的选择不如数据的使用方式重要。如果您想对大量顺序数据进行小型计算,则最好使用小型数据类型。在小数据集上进行大量计算将允许您使用更大的数据类型并产生任何显着影响。如果你' 重新非常随机地访问数据,那么数据大小的选择并不重要 - 数据加载在页面/缓存行中。因此,即使您只需要 RAM 中的一个字节,也可以传输 32 个字节(这非常依赖于系统的架构)。除此之外,CPU/FPU 可以是超标量(又名流水线)。因此,即使加载可能需要几个周期,CPU/FPU 也可能忙于做其他事情(例如乘法),这在一定程度上隐藏了加载时间。

  5. 该标准不强制浮点值的任何特定格式。

如果您有一个规范,那么它将引导您做出最佳选择。否则,要体验使用什么。

于 2009-07-02T14:43:54.203 回答
16

Double 更精确,但编码为 8 个字节。float 只有 4 个字节,所以空间更小,精度也更低。

如果您的应用程序中有 double 和 float ,您应该非常小心。由于过去,我有一个错误。一部分代码使用浮点数,而其余代码使用双精度。将 double 复制到 float,然后将 float 复制到 double 可能会导致精度错误,从而产生很大影响。就我而言,它是一家化工厂……希望它不会产生严重的后果:)

我想,几年前阿丽亚娜6号火箭爆炸的原因就是这种bug!!!

仔细考虑要用于变量的类型

于 2009-07-02T14:21:15.187 回答
5

我个人一直都在加倍,直到我看到一些瓶颈。然后我考虑移动到浮动或优化其他部分

于 2009-07-02T13:57:59.740 回答
4

这取决于编译器如何实现双精度。double 和 float 是同一类型是合法的(并且在某些系统上)。

话虽如此,如果它们确实不同,主要问题是精度。由于大小不同,double 具有更高的精度。如果您使用的数字通常会超过浮点数的值,则使用双精度数。

其他几个人提到了性能问题。这将是我考虑清单中的最后一个。正确性应该是您的第一考虑因素。

于 2009-07-02T13:58:44.903 回答
3

使用所需的精度来获得适当的结果。如果你发现你的代码没有达到你想要的效果(你使用了正确的分析?)看看:

于 2009-07-02T14:04:15.703 回答
2

我认为无论差异如何(正如每个人都指出的那样,浮动占用的空间更少并且通常更快)......有没有人使用双倍遇到性能问题?我说使用双倍......如果稍后你决定“哇,这真的很慢”......找到你的性能瓶颈(这可能不是你使用双倍的事实)。那么,如果它对你来说仍然太慢,看看你可以在哪里牺牲一些精度并使用浮点数。

于 2009-07-02T14:01:51.043 回答
1

double 具有更高的精度,而浮点数占用更少的内存并且速度更快。一般来说,你应该使用浮点数,除非你有一个不够准确的情况。

于 2009-07-02T13:55:40.713 回答
1

float 和 double 之间的主要区别在于精度。维基百科有更多关于 Single precision (float) 和Double precision的信息。

于 2009-07-02T13:58:04.327 回答
1

它高度依赖于 CPU,最明显的权衡是在精度和内存之间。使用 GB 的 RAM,内存不是什么大问题,因此通常最好使用doubles.

至于性能,很大程度上取决于CPU。在 32 位机器上,floats 通常会获得比 s 更好的性能。double在 64 位上,doubles 有时更快,因为它(通常)是本机大小。尽管如此,比您选择的数据类型更重要的是您是否可以利用处理器上的 SIMD 指令。

于 2009-07-02T14:14:53.543 回答