为什么Box2D必须使用浮点值?

时间:2014-03-07 05:18:26

标签: java floating-point jbox2d

在使用JBox-2D引擎查看代码之后,很明显经常使用float声明:

float x = 20.0f //<-- float

FixtureDef fixDef = new FixtureDef();
fixDef.shape = shape;
fixDef.density = 0.0f; //<-- float
fixDef.friction = 0.9f; //<-- float

我已经修改了一下,发现当代码没有表示为浮点时,代码正确符合。因此,我的问题是:

为什么编码器必须将值定义为JBox-2D中的浮点数,即使它存储的变量已经被声明为浮点数?

1 个答案:

答案 0 :(得分:3)

如果将一个像0.9这样的数字分配给一个浮点数,那么在某些情况下,如果它被声明为0.9f,那么结果将更准确,如果它被声明为0.9,这是一个双精度数,然后从双重浮动。将它声明为浮点字面值,使用“f”,将永远不会比将其声明为double并且使其浮动更糟糕。

与向float文字声明相同的值相比,将一个int文字赋值给float不会有精度损失,但是如果所有内容都是在float中完成的,那么使所有文字浮动,而不仅仅是非整数的。这样,如果文字后来从整数变为分数,则“f”已经存在。

=============================================== =================================

问题的根源是在从十进制字符串转换为double的过程中丢失有关文字的信息。以下是如何发生这种情况的示例。

假设小数部分略大于两个正好在两个相邻浮点数中间的两倍,并且两个浮点数中的较低者是偶数(最后一位为零)。

小数部分越接近两个浮点数中的较大者,因此在直接转换为浮点数时会向左舍入。如果转换是通过double完成的,则舍入为double会丢失该信息。 double to float转换使用round-half-even,它将两个相邻浮点数之间的双半映射到偶数转换,在这种情况下是较小的一个。

这是一个证明这一点的程序:

import java.math.BigDecimal;

public class Test {
  public static void main(String[] args) {
    BigDecimal exactValue = new BigDecimal("1.5000000596046447753906251");
    System.out.println("Exact = " + exactValue);

    double d = 1.5000000596046447753906251;
    BigDecimal dValue = new BigDecimal(d);
    System.out.println("dValue = " + dValue);

    float f1 = 1.5000000596046447753906251f;
    BigDecimal f1Value = new BigDecimal(f1);
    System.out.println("f1Value = " + f1Value);

    float f2 = (float) 1.5000000596046447753906251;
    BigDecimal f2Value = new BigDecimal(f2);
    System.out.println("f2Value = " + f2Value);

    System.out.println("f1 error = "
        + exactValue.subtract(f1Value).abs());
    System.out.println("f2 error = "
        + exactValue.subtract(f2Value).abs());
  }
}

输出:

Exact = 1.5000000596046447753906251
dValue = 1.500000059604644775390625
f1Value = 1.50000011920928955078125
f2Value = 1.5
f1 error = 5.96046447753906249E-8
f2 error = 5.96046447753906251E-8

直接转换结果f1的绝对舍入误差小于f2的绝对舍入误差,即通过double转换的结果。