简体   繁体   English

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

[英]Java: Perform mathematical operation while ignoring sign

I am trying to make a game involving the calcualtion of forces needed to perform some simple mathematical operations. 我正在尝试制作一个涉及进行一些简单数学运算所需的力计算的游戏。 I have a dx variable that represents both the speed and direction along the X-axis. 我有一个dx变量,代表沿X轴的速度和方向。 Now I want to subtract friction but it would have to be an addition if the direction of dx is negative. 现在,我想减去摩擦,但是如果dx的方向为负,则必须加法。 Is there any way to subtract friction from dx using absolute values while returning a signed value? 有什么方法可以使用绝对值从dx减去摩擦,同时返回带符号的值? I was looking in to bitwise operators but I have no idea what the possibilities are... 我一直在寻找按位运算符,但我不知道有什么可能...

What I could do (i think): 我能做的(我认为):

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

Not sure if this would work, just the idea... Any improvements? 不知道这是否行得通,只是想法...任何改进?

Edit: this is what I did: 编辑:这就是我所做的:

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;

The safest option is to use a condition. 最安全的选择是使用条件。 You don't want fraction to change direction 您不希望分数改变方向

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

Your code is incorrect, for two reasons: 您的代码不正确,原因有两个:

  • dx = (dx << 1) >> 1; does not eliminate the sign. 不消除迹象。 Moreover, it may incorrectly produce a "false positive" (ie a falsely negative number) when bit 31 is set to 1 . 此外,当位31设置为1时,可能会错误地产生“假正数”(即假负数)。 Even if you replace >> with >>> you would not get an absolute value, because int s are stored in two's complement, not as a sign + value representation 即使将>>替换为>>> ,也不会得到绝对值,因为int是以二进制补码形式存储的,而不是用符号+值表示
  • sign will be either a 10000...00 or 00000..00 in binary representation, so ( dx - friction ) & sign will not merge the sign with the results of the other calculation. sign将是二进制表示形式的10000...0000000..00 ,因此( dx - friction ) & sign 00000..00 ( dx - friction ) & sign不会将符号与其他计算的结果合并。

You can change the addition for subtraction with the Integer.signum function, like this: 您可以使用Integer.signum函数将加法更改为减法,如下所示:

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

Just do it the obvious way: don't try to be clever unless this has performance issues. 采取明显的方法即可:除非遇到性能问题,否则请不要变得聪明。

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

If that seems a bit verbose, hide it in a method: 如果这看起来有些冗长,请将其隐藏在方法中:

dx = applyFriction(dx,friction);

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

This has issues when abs(pos) < friction , and if you look into your physics, you'll find it's more likely that friction is simulated by multiplying - which removes your concern about sign. abs(pos) < friction ,就会遇到问题,如果您研究物理学,您会发现更可能通过乘以模拟摩擦,从而消除了对符号的担忧。

Use Math.abs when you want to ignore the sign. 当您想忽略符号时,请使用Math.abs Be aware that optimization might result in your code becoming unreadable and difficult to maintain. 请注意,优化可能导致您的代码变得不可读且难以维护。 So, for starters try to make your code as clean and possible and when you encounter performance issues, determine the source of your problem by benchmarking and optimize only the bottleneck of your code. 因此,对于初学者来说,请尝试使您的代码尽可能整洁,并在遇到性能问题时,通过进行基准测试确定问题的根源,并仅优化代码的瓶颈。

In physics, the sign of your direction doesn't really matter. 在物理学中,方向的指示并不重要。 I suggest using the fact that the kinetic friction is a force which is proportional to absolute velocity of the object in motion. 我建议利用以下事实:动摩擦是与运动中物体的绝对速度成比例的力。 That is, the object has some coefficient of friction μ F in the range [0, 1] . 即,物体具有在[0, 1]范围内的一些摩擦系数μ F The change in velocity is just δ V = μ FV ∙δ t where V is the initial velocity vector of your object, and δ t is some span of time. 在速度变化只是δ V = μ FV ∙δ t ,其中V是您的物体的初始速度矢量和δ t是时间跨度一些。

The new velocity V' is given by 新速度V'由下式给出

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

In this way, you don't need to deal with the sign at all, and it extends easily into higher dimensional cases. 这样,您根本不需要处理符号,它可以轻松扩展到高维案例中。

As an aside, make sure δ t is small enough that it doesn't introduce an oscillation in your model. 顺便说一句,请确保δt足够小,以免在模型中引起振荡。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM