Java:忽略符号时执行数学运算

时间:2014-05-07 12:42:53

标签: java math integer bit-manipulation sign

我正在尝试制作一个涉及计算执行一些简单数学运算所需力的游戏。我有一个dx变量,表示沿X轴的速度和方向。现在我想减去摩擦,但如果dx的方向为负,则必须添加。有没有办法在返回有符号值时使用绝对值减去dx的摩擦力?我正在寻找按位运算符,但我不知道可能性是什么......

我能做什么(我认为):

sign = ( dx >> 31 ) << 31;
dx = (dx << 1) >> 1;
dx = ( dx - friction ) & sign;

不确定这是否有用,只是想法......有什么改进吗?

编辑:这就是我所做的:

dxSign = Integer.signum(dx) * -1;
dySign = Integer.signum(dy) * -1;
dy = Math.abs(dy);
dx = Math.abs(dx);

fric = body.friction * mass;

dx = ( dx > fric ) ? dx - fric : 0;
dy = ( dy > fric ) ? dy - fric : 0;

dx = dx * absorption;
dy = dy * absorption;

dx *= dxSign;
dy *= dySign;

5 个答案:

答案 0 :(得分:2)

最安全的选择是使用条件。你不希望分数改变方向

dx = dx < -friction ? dx + friction : dx > friction ? dx - friction : 0

答案 1 :(得分:1)

您的代码不正确,原因有两个:

  • dx = (dx << 1) >> 1;不会消除这个标志。而且,当位31被设置为1时,它可能错误地产生“误报”(即,错误的负数)。即使您将>>替换为>>>,也不会获得绝对值,因为int存储在二进制补码中,而不是作为符号+值表示
  • sign将是二进制表示中的10000...0000000..00,因此( dx - friction ) & sign不会将该符号与其他计算的结果合并。

您可以使用Integer.signum功能更改减法的加法,如下所示:

dx -= Integer.signum(dx) * friction;

答案 2 :(得分:1)

只是以明显的方式做到这一点:除非出现性能问题,否则不要试图变得聪明。

if(dx >0 ) {
    dx -= friction;
} else {
    dx += friction;
}

如果这看起来有点冗长,请将其隐藏在方法中:

dx = applyFriction(dx,friction);

int applyFriction(int pos, int friction) {
     if(pos > 0) {
           return pos - friction;
     } else {
           return pos + friction;
     }
}

abs(pos) < friction时出现此问题,如果你研究一下你的物理特性,你会发现通过乘法模拟摩擦的可能性更大 - 这可以消除你对符号的担忧。

答案 3 :(得分:1)

如果要忽略该符号,请使用Math.abs。请注意,优化可能会导致代码变得难以理解且难以维护。因此,对于初学者来说,尝试使您的代码变得干净和可能,当您遇到性能问题时,通过基准测试确定问题的根源,并仅优化代码的瓶颈。

答案 4 :(得分:1)

在物理学中,你的方向标志并不重要。我建议使用这样的事实,即动摩擦力是一个与运动中物体的绝对速度成正比的力。也就是说,对象在μF范围内具有一些摩擦系数[0, 1]。速度的变化只是δV = μFV∙δt,其中 V 是对象的初始速度向量,δt是一段时间。

新的 V'

提供
V' = V - δV
   = V - μFV∙δt
   = V(1 - μF∙δt)

通过这种方式,你根本不需要处理这个符号,它很容易扩展到更高维度的情况。

另外,确保δ t 足够小,不会在模型中引入振荡。