1

可能永远result是假的,因为4 / 2.0可能会返回类似的东西1.99999999?比标题更笼统:

int a = // any valid int
int b = // any valid int
boolean result = (a/(double)b) >= a/b;

如果这是可能的,任何人都可以提供一个a和的例子b吗?如果这不可能,是否有任何 java 或浮点规范可以证明这一点?

几分钟前我写了这个逻辑,突然担心它会崩溃。我一直无法打破它,但我想知道它是否在所有 JVM 中都能得到保证。

4

3 回答 3

5

如果ab是正值int,那么a/(double)b >= a/b

我使用以下前提以及理解的语义,例如将 的inta/b转换double为与 的其他操作数进行比较>=

前提:

  • 的范围int是 [-2,147,483,648, 2,147,483,648)。
  • double是 IEEE 754 64 位二进制。
  • 舍入模式是舍入到最近的。
  • 所有浮点运算,尤其是除法,都符合 IEEE 754。
  • 整数a/b向零截断。

符号:

  • a是 的数学值a
  • b是 的数学值b
  • 数学表达式(例如a / b)是精确的,与计算表达式(例如a/b.
  • L为 为 产生的值a/(double)b
  • R为 为 产生的值a/b

证明:

  • 所有int值都可以在 中表示double,因此 IEEE 754 要求转换int准确double
  • 因此,准确(double) a(double) b产生ab,并a/(double)b产生正确舍入到最接近的 a / bdouble
  • 由于R是向零截断的a / b ,并且a / b是正数,因此R是 floor( a / b )。
  • 最大的 a / b可以是 2,147,483,647/1 = 2,147,483,647。这个数量级及以下的每个整数都可以精确地表示为 a double
  • Ldouble最接近的 a / b。如果L通过四舍五入减少,则减少到下一个较低的double。由于这个量级的所有整数都是可表示的,所以 floor( a / b ) 是可表示的,所以L至少是 floor( a / b )。
  • 因此LR
  • R to的转换double是精确的,因此LR的比较产生与数学LR>=相同的结果。
于 2013-03-12T01:47:35.773 回答
2

对于负数,它在 a = -10, b = 3 时失败。

仅对于积极的输入,我认为您是安全的。

令 x 为 a 除以 b 的实数结果。

首先考虑 x 可以表示为 int 的情况。它也可以表示为双精度,并且两个计算都返回 x。

现在假设 x 不是 int。问题是 x 和 a/(double b) 之间的舍入误差差的绝对值是否可以超过 a/b 的截断误差。这不可以。

截断误差 t = x - a/b 必须至少为 1/b。x 不能大于 Integer.MAX_VALUE/b,因此 t/x 至少为 1/Integer.MAX_VALUE。这远大于正确舍入双精度计算的最大舍入误差。

于 2013-03-12T01:44:12.160 回答
0

4 / 2.0必须返回2.0,因为浮点除法是精确的。

但是,负数可能会导致您的比较失败。请注意,-1/2 = 0虽然-1.0/2.0 = -0.5.

于 2013-03-12T00:45:27.657 回答