浮点错误会导致'a /(double)b> = a / b'失败吗?

时间:2013-03-12 00:43:09

标签: java floating-point

result可能会错误,因为4 / 2.0可能会返回1.99999999之类的内容吗?比标题更普遍:

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

如果可以,有人可以提供ab的示例吗?如果这是不可能的,是否有任何证明这一点的java或浮点规范?

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

3 个答案:

答案 0 :(得分:5)

如果ab的值为int,则为a/(double)b >= a/b

我使用以下前提以及理解的语义,例如int的{​​{1}}值将转换为a/b,以便与{{1}的其他操作数进行比较}}

物业:

  • double的范围是[-2,147,483,648,2,147,483,648]。
  • >=是IEEE 754 64位二进制文​​件。
  • 舍入模式是最接近的。
  • 所有浮点运算,特别是除法,均符合IEEE 754。
  • 整数int截断为零。

符号:

  • a double的数学值。
  • b a/b的数学值。
  • 数学表达式,例如 a / b ,是精确的,与a等计算表达式不同。
  • L b生成的值。
  • R a/b生成的值。

证明:

  • 所有a/(double)b值均可在a/b中表示,因此IEEE 754要求将int转换为double
  • 因此,intdouble完全生成 a b (double) a生成 a / b 正确舍入到最近的(double) b
  • 由于 R a / b 被截断为零,而 a / b 是正面的, R 是底线( a / b )。
  • 最大的 a / b 可以是2,147,483,647 / 1 = 2,147,483,647。此大小及以下的每个整数都可以表示为a/(double)b
  • L double最近的 a / b 。如果通过舍入减少 L ,则减少到下一个double。由于此幅度的所有整数都是可表示的,因此floor( a / b )是可表示的,因此 L 至少为floor( a / b'/ I>)。
  • 因此 L R
  • R 转换为double是准确的,因此 L R double的比较产生与数学 L R 相同的结果。

答案 1 :(得分:2)

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

仅对于积极的投入,我认为你是安全的。

设x是除以b的实数结果。

首先考虑x可表示为int的情况。它也可以表示为double,两个计算都返回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。这远远大于正确舍入的双重计算的最大舍入误差。

答案 2 :(得分:0)

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

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