我有一个矢量类(2D数学矢量),其中float
为其组成部分。
对于某些中间计算,我可以选择使用双打。我应该尽可能长时间地使用中间双精度,只能在最后进行浮动,或者最好尽快将任何双精度投射到浮子上吗?
例如,以下是矢量标准化的两种可能实现方式。
首先,保持所有计算的加倍:
public class Vector2f {
private float x;
private float y;
....
public Vector2f normalize() {
double length = Math.sqrt((x * x) + (y * y));
return new Vector2f(
(float) (x / length),
(float) (y / length)
);
}
}
其次,立即转换为浮动:
public Vector2f normalize() {
float length = (float) Math.sqrt((x * x) + (y * y));
return new Vector2f(
x / length,
y / length
);
}
答案 0 :(得分:4)
一般来说,尽可能长时间保持精度总是更好,特别是如果你的值非常小/接近于零。
尝试以下几行:
System.out.println(0.00001f * 0.00002f / 0.00000003f);
System.out.println(0.00001d * 0.00002d / 0.00000003d);
输出将是:
0.0066666664
0.006666666666666668
哪一个更好,你怎么看?因此,这些错误可能会累积在您的计算中并影响您的输出。
让它更有趣:
System.out.println(0.00001f * 0.00002f * 0.00000003f* 0.00000003f* 0.00000003f* 0.00000003f* 0.00000003f * 0.00000003f / 0.00000003f / 0.00000003f / 0.00000003f / 0.00000003f/ 0.00000003f/ 0.00000003f);
System.out.println(0.00001d * 0.00002d * 0.00000003d* 0.00000003d* 0.00000003d* 0.00000003d* 0.00000003d * 0.00000003d / 0.00000003d / 0.00000003d / 0.00000003d / 0.00000003d/ 0.00000003d/ 0.00000003d);
并输出:
0.0
2.0000000000000003E-10
注意小值!
答案 1 :(得分:0)
最终从double转换为float的结果将比在这些操作之前转换的结果更准确。
x / length,
y / length
解决方案似乎比其他解决方案更好。