【问题标题】:What are the downsides of replacing all integers with doubles?用双精度数替换所有整数有什么缺点?
【发布时间】:2021-10-03 08:43:35
【问题描述】:

始终使用浮点类型来表示整数有哪些潜在的缺点,即使在索引到数组时也是如此?假设一个面向性能的 C 库的上下文。在 64 位整数和 64 位浮点之间进行选择。

我对做这样的事情感到不舒服,因为doubles 不意味着用于索引,并且将工具用于它不是为它设计的东西通常会带来风险。但我想了解是否有合理的理由避免这样做。

把显而易见的事情排除在外:

  • 当然,在 double[ ] 运算符一起使用时可能需要进行一些强制转换。
  • 当然,IEEE 754 double 不能像 64 位整数类型那样表示尽可能多的不同整数,但在可预见的未来,53 位可能已经足够索引数组了。

事实上,浮点类型的这种用法很普遍。例如,R 没有 64 位整数,并且通过使用 doubles 进行索引来支持大型数组。在编写必须与 R 互操作的代码时,必须考虑是否要这样做。

【问题讨论】:

  • 如果 Javascript 不足以让你远离这种愚蠢的行为,那么大概什么都不会。
  • @EOF 我不懂 Javascript。我发现自己处于一种正在考虑这一点的情况(因为 R),虽然它“感觉是个坏主意”,但我希望收集一些理性的论据,而不是仅仅遵循感觉对或错的观点。
  • 它肯定会慢得多并且可能占用更多空间(除非您将 double 与 64 位整数进行比较)。在某些没有 F​​P 单元的嵌入式处理器上尤其如此,因此模拟此类操作非常慢(例如,整数运算的 100 倍以上)。
  • 浮点计算比整数计算需要更多的周期。因此,对于性能敏感的应用程序/库,它很可能不是一个好的选择。
  • 与被(编辑)污染的软件交互是我们许多人必须不时忍受的事情。然而,有一个选择。您可以将(编辑的)严格限制在界面边界,或者让它传播并接管您的整个世界。明智地选择。

标签: c performance floating-point


【解决方案1】:
  1. 性能:在许多 CPU 架构上,浮点运算比整数运算慢。 Floating point vs integer calculations on modern hardware 这在很大程度上取决于操作类型和相关 CPU。这可能无关紧要,如果代码没有被大量使用(分析为 Hot)或者它对于应用程序来说“足够好”。
  2. 表示法:浮点数通常以 2 为基数表示,并非所有(可精确表示的以 10 为基数的)数字都可以准确表示。 When is it appropriate to use floating precision data types? 这对算术有影响,可能会产生意想不到的结果。 Fun times
  3. 比较:由于表示困难,一些 linter 和库不允许浮点之间的相等检查。 SonarSource Java rule xUnit Assert library (note absence of Equals(double double)) 这是为了减少错误的可能性,但可能会影响您将双精度数用作整数。
  4. Principle of least astonishment:在通常需要整数的地方使用浮点数会导致更努力地理解代码,这反过来又使维护和更改变得更加困难。
  5. 对整数原生语言的支持很差:在使用整数作为主要类型的语言(例如 C)中,使用浮点代替整数会导致与语言的其余部分和可能的许多库的“摩擦”增加。本质上,在您的示例中,您是在与 R 进行互操作,以换取与 C 的“互操作”。

为了与(几乎任何语言,甚至库)进行互操作,我建议创建一个互操作层或组件来处理它可以处理的所有问题并记录那些它不能解决的问题,本质上是抽象掉(一些)互操作的复杂性。

【讨论】:

  • 第 3 点不正确。当且仅当两个操作数表示相同的数字时,比较两个浮点数的相等性评估为真。这个操作从来没有任何错误,它不是“特定于实现的”。这个神话的原因是天真的程序员试图比较包含先前操作的错误的操作数,并且可能不知道如何处理这些错误。但这些错误是由先前的算术运算产生的,如第 4 点所示,而不是比较。
  • 第 2 点和第 4 点是同一事物的未完全陈述的方面:浮点运算产生的结果等同于四舍五入到最接近的可表示值的实数结果。
  • 顺便说一句,10/3•3 以任何基于二进制的浮点格式生成 10,并具有四舍五入到最接近、平成的关系。 10/3 的无限精确结果将是二进制的 11.01010101……如果有效数字的位数为偶数,则重复以 1 结束,因此结果向下舍入。然后乘以 3 得到 1001.1111…11,其中两位超出有效位宽度,因此将 11 向上舍入,得到 10。如果位为奇数,则将商向上舍入,得到 11.010101…01011。乘以 3 得到 1010.000…01,再次超出两位,因此 01 向下舍入。
  • 编辑点 3.
  • 对不起,比较小于或等于与比较相等是一样的;它总是正确的。当且仅当a 表示小于或等于b 的数字时,a <= b 的计算结果为 true。其他操作可能有错误,但比较起来没有。尽管如此,使用<= 并不能解决使用== 的问题。如果之前的操作有错误,那么<=== 的操作数是错误的,使用一个或另一个将无法解决这个问题。
猜你喜欢
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 2010-10-22
  • 1970-01-01
  • 2014-01-30
  • 2020-05-28
  • 1970-01-01
相关资源
最近更新 更多