在使用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中的浮点数,即使它存储的变量已经被声明为浮点数?
答案 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转换的结果。