【问题标题】:Should I use double or float?我应该使用双精度还是浮点数?
【发布时间】:2010-11-07 15:37:05
【问题描述】:

在 C++ 中使用一种代替另一种的优点和缺点是什么?

【问题讨论】:

  • 有没有人尝试过制作一个浮点数组和一个双精度数组,看看浮点数成员之间是否确实有 4 个字节,双精度成员之间是否确实有 8 个字节?一个 64 位编译器/计算机可能仍然为每个成员保留 8 个字节用于浮点数,即使它们不需要那么多。

标签: c++ types floating-point double-precision


【解决方案1】:

如果你想知道真正的答案,你应该阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic

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

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

【讨论】:

  • 是的。随着现代 CPU 预取越来越大的内存块、并行数值处理单元和流水线架构,速度问题真的不是问题。如果您正在处理大量数字,那么 4 字节浮点数和 8 字节双精度数之间的 size 差异可能会影响内存占用。
  • 与双精度相比,SSE(或任何vertor浮点单元)将能够处理两倍的单精度触发器。如果您只是在做 x87(或任何标量)浮点,那么它可能无关紧要。
  • @Greg Rogers:编译器目前还没有那么聪明。除非您正在编写原始程序集,否则它没有太大的不同。是的,这可能会随着编译器的发展而改变。
  • 附加说明:如果您完全不知道数据是什么样子(或者只是对链接中的所有数学一无所知),请使用double——在大多数情况下更安全案例。
  • @jokoon,浮点和整个精度/数值稳定性问题领域没有什么简单的。
【解决方案2】:

除非您有其他特殊原因,否则请使用 double。

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

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

【讨论】:

    【解决方案3】:

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

    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. 该标准不强制浮点值使用任何特定格式。

    如果您有一个规范,那么它将引导您做出最佳选择。否则,就看用什么了。

    【讨论】:

      【解决方案4】:

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

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

      我觉得是阿丽亚娜六号火箭几年前爆炸的原因就是这种bug!!!

      仔细考虑变量的类型

      【讨论】:

      • 请注意,甚至不能保证浮点/双精度的 4/8 字节,这取决于平台。它甚至可能是同一类型...
      • Ariane 5 代码尝试将大于 32,767 的 64 位浮点数转换为 16 位有符号整数。这产生了一个溢出异常,导致火箭启动其自毁序列。有问题的代码是从更旧、更小的火箭中重复使用的代码。
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

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

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

        【讨论】:

          【解决方案7】:

          【讨论】:

            【解决方案8】:

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

            【讨论】:

              【解决方案9】:

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

              【讨论】:

              • 在典型的现代计算机上,double 与 float 一样快。
              【解决方案10】:

              float 和 double 的主要区别在于精度。维基百科有更多关于 Single precision(浮点数)和Double precision

              【讨论】:

                【解决方案11】:

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

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

                【讨论】:

                  猜你喜欢
                  • 2016-06-24
                  • 1970-01-01
                  • 2013-05-07
                  • 2018-02-23
                  • 2018-07-06
                  • 2017-03-25
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多