我经常需要这种功能,例如,为了理解iPhone触摸的方向以及解决这个问题的唯一方法就是使用逻辑,如下所示:
int dir,distY;
distY = newY-oldY;
if (distY > 0)
{
dir = 1;
}
else if (distY < 0)
{
dir = -1;
}
我想知道是否有办法通过数学方法或时尚的老派方式在一个拍摄mybey中进行。
澄清,我正在寻找的类似例子是:
i = ++i % max;
而不是:
i++;
if ( i > max ) { i = 0; }
答案 0 :(得分:2)
如果您知道该值将非零,则可以除以绝对值:
dir = distY / abs(distY);
如果它可能为零,并且你仍然希望将标志设置为某个东西,你可以做这样的事情(在C / C ++中):
dir = distY >= 0 ? 1 : -1;
当distY为零时,这会将dir设置为1.
答案 1 :(得分:2)
假设您正在使用C或C ++之类的东西将true转换为1而false为0,则可以使用:direction = (distY > 0) - (distY < 0);
。在distY=0
时你没有说出你想要的东西 - 这给了0(这对我来说似乎是明显的选择,但谁知道)。
当然,不能保证它会有任何好处 - 这将取决于编译器,编译器标志,CPU,甚至可能是月相的组合。 OTOH,我猜它有更多的机会做好事而不是伤害。
答案 2 :(得分:1)
direction = dirtY /和(dustY)
但是你仍然需要检查以确保distY不是0。
答案 3 :(得分:1)
您似乎正在寻找signum
功能。如果您的编程语言/库没有它,那么编写起来非常简单:只需将if / else语句包装在一个函数中,这样就可以更容易和更好地使用它。
用数学符号:
sign(n) =
|-1 if n < 0
| 0 if n = 0
| 1 if n > 0
如果速度较慢或较快,则位操作取决于语言,目标平台和库(如果使用的话)。以任何方式参与abs
(如某些答案中所建议的)可能是一种矫枉过正,因为它将在内部包含几乎相同的逻辑,并且您还有一个呼叫和分组+您必须处理潜在的分裂零。
答案 4 :(得分:0)
如果你坚持要简洁,试试
(i>0)?1:((i<0)?-1:0)
(假设您想以最明智的方式覆盖零案例)。
可能存在使用符号位移位的黑客攻击,但我怀疑它们是优雅还是高效。
就个人而言,我会使用if-else结构。
答案 5 :(得分:0)
如果您使用的语言中0为false且1为真(或提供类型转换),则使用伪代码:
i = abs(distY) == distY; // 0 or 1
i = i*2 - 1; // -1 or 1
答案 6 :(得分:0)
你可能会告诉我C中是否有类似的东西,但Perl只有这个工作的相等运算符。
<=>
运算符的使用方式如下:
$dir = $distY <=> 0;
从文档(perldoc perlop
):
二进制
"<=>"
返回-1,0或1,具体取决于左参数是否在数值上小于,等于或大于右参数。
现在我想知道的是C,C ++和/或Objective-C中是否存在类似内容。
答案 7 :(得分:0)
在支持基本位操作(移位)的任何语言中,这都有效 - 即使该语言未明确使用0
和1
用于FALSE
和TRUE
。
C#样本:
// Explanatory version:
static int Sign(int val)
{
val = -(int)((uint)val >> 31); // int is 32 bit, so shift by n - 1.
// uval now contains -1 for negative and 0 for positive.
return val * 2 + 1;
// -1 * 2 + 1 = -1
// 0 * 2 + 1 = +1
}
// Terse form:
static int Sign(int val)
{
return 1 - (int)((uint)val >> 31) * 2;
}
这是因为在小端two's complement硬件(如x86 / x64)上如何表示负数。基本上,对于负值,数字中的第一位将为“1”(参见示例文章)。
AND
进行0x80000000
操作。这样就可以从值中消除与符号无关的位。我们不需要这样做是因为轮班的工作方式(如果你的语言只有ROL和ROR,你需要首先进行此操作)。2^0
处留下1或0。这意味着如果值为负,则值为1,如果为正,则为0。如果您的目标是big-endian,我认为只需更改班次即可获得正确的结果。