两个正浮点数的乘积可以是负数吗?

时间:2017-09-30 12:44:28

标签: floating-point

最近查看一段代码时,我遇到了一条让我思考的问题:

if a*b > 0:
  # do stuff

应该假设ab是浮点数。

  

问题:
  是否存在ab的非常小的,正的,可能接近~ep_mach的值,使得它们的产品是负的?如果没有,我们可能a*b==0同时没有a==0b==0

不要完全懈怠,这是我的想法:

  1. 不可以,因为在FP算术中,产品很可能被定义为ab的符号位确定a*b的符号位。因此,在某些基级,计算运行“a的注释符号位为正。注意b的符号位为正。将a*b的符号位设置为正。”我想这个约定是指定的,并且在它存在的情况下被普遍分类某处

  2. a*b==0 a!=0b!=0似乎无疑是可能的。

  3. 答案取决于计算机和语言。

  4. 这引出了一个子问题:

      

    问题:
      实现下面的代码会更安全吗?如果它不安全,那该怎么办呢?

    if (a>0 and b>0) or (a<0 and b<0):
      # do stuff
    

2 个答案:

答案 0 :(得分:3)

这两段代码并不相同,因为两个正数但很小的数字的乘积确实可以为零。

哪个是正确的取决于测试的真正含义。

如果后续代码需要产品严格为正,则需要a*b > 0表单,而不是单个值的测试。

如果每个值都需要严格为正,请测试。

如果要求是非零并且具有相同的符号,那么您提出的测试是正确的。

这是一个测试某些案例的Java程序,包括微小但严格正面的案例:

public class Test {
  public static void main(String[] args) {
    testit(Double.MIN_VALUE, Double.MIN_VALUE);
    testit(-Double.MIN_VALUE, -Double.MIN_VALUE);
    testit(1e-320, 1e-320);
    testit(1e300, 1e300);
  }

  public static void testit(double a, double b) {
    System.out.println("a="+a+" b="+b);
    System.out.println("a*b > 0 " + (a * b > 0));
    System.out.println("(a>0 && b>0) " + (a > 0 && b > 0));
    System.out.println("(a<0 && b<0) " + (a < 0 && b < 0));
    System.out.println();
  }
}

答案 1 :(得分:2)

根据IEEE-754标准(使用默认舍入模式),任何浮点运算(blah blah transcendentals)的结果四舍五入到最接近的可表示数字。任何两个正数的乘积都是正数,因此最坏的情况是,最接近的可表示数字为零。最接近的可表示数字无法为负数。

您建议的替代代码是正确的。对于具有sgn / signum功能的语言,您还可以执行if sgn(a)*sgn(b) > 0之类的操作。