Java和浮点运算

时间:2015-06-23 15:46:41

标签: java floating-point floating-accuracy

拥有代码

public static final float epsilon = 0.00000001f;

public static final float a [] = {
        -180.0f,
        -180.0f + epsilon * 2,
        -epsilon * 2
}

a初始化如下:

[-180.0, -180.0, -2.0E-8]

而非期望的

[-180.0, X, Y]

如何调整epsilon以达到预期效果? -


1)我希望float而不是double与之前编写的代码保持一致  
2)我不希望-179.99999998X的任何其他特定号码,我希望X > -180.0X尽可能接近-180.0 }  
3)我希望Y尽可能接近0,但要成为float  
4)我想要-180.0 < X < Y

在我的帖子中,我没有准确说明我想要的内容。 Patricia Shanahan通过建议Math.ulp

猜测了这一点

3 个答案:

答案 0 :(得分:3)

根据之前的答案中的建议,最佳解决方案是使用double。但是,如果您想使用float,则需要考虑其感兴趣区域的可用精度。此程序将您的文字epsilon替换为与180f的最低有效位相关联的值:

import java.util.Arrays;

public class Test {
  public static final float epsilon = Math.ulp(-180f);

  public static final float a [] = {
          -180.0f,
          -180.0f + epsilon * 2,
          -epsilon * 2
  };

  public static void main(String[] args) {
    System.out.println(Arrays.toString(a));
  }

}

输出:

[-180.0, -179.99997, -3.0517578E-5]

答案 1 :(得分:0)

虽然值0.00000001ffloat的精确容量范围内,但值-180f + 0.00000001f * 2-179.99999998float只有大约7-8个有效数字的精度,-179.99999998至少需要11个。所以它的最低有效位被the addition operation删除,并且不精确的值最终成为-180.0f

只是为了好玩,here are those values in bitsn = -180.0f):

           sign
           | exponent       significand
           - -------- -----------------------
epsilon  = 0 01100100 01010111100110001110111
epsilon2 = 0 01100101 01010111100110001110111
n        = 1 10000110 01101000000000000000000
result   = 1 10000110 01101000000000000000000

结果最终与原始-180.0f相同。

如果您使用double,那个问题goes away,因为您的精确度不超过double〜15位数。

答案 2 :(得分:-2)

尝试“加倍”键。如果这还不够,请尝试“long double”。