【问题标题】:Is x/a the same as x*(1/a) for floats?x/a 是否与浮点数的 x*(1/a) 相同?
【发布时间】:2023-03-14 21:20:01
【问题描述】:

float a = ...;float inva = 1/a;x / a 相同x * inva

这个案子是怎么回事:

unsigned i = ...;
float v1 = static_cast<float>(i) / 4294967295.0f;
float scl = 1.0f / 4294967295.0f;
float v2 = static_cast<float>(i) * scl;

对于所有无符号整数,v1 是否等于 v2

【问题讨论】:

  • 这里的第一个答案可能会为您提供一些信息:stackoverflow.com/questions/22621241/…
  • @devnull: 该站点已死。
  • 不是重点,但4294967295.0f 甚至不能表示为浮点数。
  • @MatthieuM。这是一个浮动。两个浮点数,如x / y == x * (1 / y),通常只产生不到 2^64 种可能性,除非您可以争辩说不需要研究大多数指数,在这种情况下,您最终可能会得到几乎不实用的 2^46 种可能性。
  • @Michael Walz 我也无法处理 32 位 unsigned 的失败案例。甚至尝试将 unsigned 作为 64 位 - 到目前为止没有失败。 (这是 OP 的第二种情况)

标签: c++ c floating-point


【解决方案1】:

对于所有无符号整数,v1 是否等于 v2

是的,因为4294967295.0f 是二的幂。当除数是 2 的幂时(假设倒数的计算不会上溢或下溢为零),除数和乘以倒数是等价的。

倒数除法和乘法一般不等价,仅在二的幂的特殊情况下。原因是对于两个y 的(几乎所有)幂,1 / y 的计算是精确的,因此x * (1 / y) 只循环一次,就像x / y 只循环一次一样。

【讨论】:

  • @Danvil 有趣的是 4294967295 不是 2 的幂,而是4294967295.0f,在大多数编译平台上,是最接近 4294967295 的单精度 IEEE 754 数,即 4294967296,以及实际上是 2 的幂。
  • 请注意,实际上可能会将 4294967295.0f 视为 == 到 4294967296.0f,因为尝试将 2^32-1 表示为浮点数时会出现精度损失问题......所以,虽然它不是真正的 2 的幂(根据定义,除了 2^0 = 1 之外,没有奇数可以是),它可能看起来是......
【解决方案2】:

不,结果并不总是相同的。在这种情况下,在浮点乘法或除法中对操作数进行分组的方式会影响答案的数值准确性。因此,产品a*(1/b) 可能与a/b 不同。查看维基百科文章http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

【讨论】:

  • 我是这么认为的,但是在整数的情况下,我找不到反例......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-10
  • 2016-05-06
相关资源
最近更新 更多