代码之家  ›  专栏  ›  技术社区  ›  Cesar

从给定的数字中,如果为负,则将var设置为-1,如果为正,则将var设置为1(不使用if)

  •  3
  • Cesar  · 技术社区  · 14 年前

    我经常需要这种功能,例如,为了理解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; }
    
    8 回复  |  直到 12 年前
        1
  •  2
  •   Jerry Coffin    14 年前

    假设你使用的东西是C或C++,它会转换为真和1,假到0,你可以使用: direction = (distY > 0) - (distY < 0); distY=0 --这就得到了0(这对我来说似乎是一个明显的选择,但谁知道呢)。

    当然,也不能保证它会有任何好处——这取决于编译器、编译器标志、CPU,甚至月球的相位。奥托,我猜不管怎样,它做好事的机会比伤害更多。

        2
  •  2
  •   Amber    14 年前

    如果你知道这个值不是零,你可以除以绝对值:

    dir = distY / abs(distY);
    

    如果它可能是零,并且你仍然想将标志设置为某个东西,那么你可以做类似的事情(C/C++):

    dir = distY >= 0 ? 1 : -1;
    

    当距离为零时,这也会将dir设置为1。

        3
  •  1
  •   Dave Markle    14 年前

    方向=distY/abs(distY)

        4
  •  1
  •   phuclv    6 年前

    看来你在找 signum

    sign(n) =  
    |-1 if n < 0  
    | 0 if n = 0  
    | 1 if n > 0
    

    如果速度较慢或较快,则位操作取决于语言、目标平台和库(如果使用)。涉及 abs

        5
  •  0
  •   Don Roby    14 年前

    如果你坚持要简洁,试试看

    (i>0)?1:((i<0)?-1:0)
    

    (假设您希望以最合理的方式涵盖零的情况)。

    就我个人而言,我会使用if-else结构。

        6
  •  0
  •   Lèse majesté    14 年前

    i = abs(distY) == distY; // 0 or 1
    i = i*2 - 1; // -1 or 1
    
        7
  •  0
  •   Zaid    14 年前

    您可能会告诉我在C中是否有类似的东西,但是Perl只为该作业提供了相等运算符。

    <=> 运算符的用法如下:

    $dir = $distY <=> 0;
    

    从文档中( perldoc perlop

    二元的 "<=>" 根据左参数在数字上是小于、等于还是大于右参数,返回-1、0或1。

        8
  •  0
  •   Jonathan Dickinson    12 年前

    在任何支持基本位操作(移位)的语言中,这都是有效的——即使该语言没有显式地使用 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”(有关示例,请参阅本文)。

    1. 在这个阶段,我们可能会 AND 使用it和 0x80000000
    2. 我们将值右移31位。移位运算符将“销毁”任何从末尾“掉”下来的位—因此,我们在该位上只剩下1或0 2^0
    3. 我们将其转换回int,然后使用简单的数学将0和1分别映射到1和-1。

    如果你的目标是big-endian,我认为只要改变移位就应该得到正确的结果。