寻找将负整数归零的.NET Math方法

时间:2010-03-24 16:05:27

标签: c# .net vb.net math

在概念上类似于Math.Abs​​() - 我正在寻找一个函数,当给定正整数时将返回相同的整数。如果给出否定,则返回零。

所以:

f(3) = 3
f(0) = 0
f(-3) = 0

是的,这很简单,我自己写,但我想知道.NET Math类是否已经内置了这个内容,或者是否可以通过巧妙地链接一些Math。*调用来实现相同的目标?

6 个答案:

答案 0 :(得分:63)

它被称为Math.Max

Math.Max(0, x)

答案 1 :(得分:32)

这似乎是你想要的,不是吗?

Math.Max(0, num);

答案 2 :(得分:14)

我认为

Math.Max(0, x)

是你想要的。

答案 3 :(得分:3)

看起来Math.Max是要走的路,但这也会起作用......;)

(num + Math.Abs(num)) / 2

答案 4 :(得分:3)

Math.Max是最好的,但没有Math和VB

(num >= 0) * -num

答案 5 :(得分:3)

给出32位带符号整数num,如果它为负,则下面的表达式返回零,否则返回原始的不变值:

(~num >> 31) & num

此操作有时称为 夹紧 ;小于零的值会固定为零。


说明

只有正整数(和零)的符号位具有0,即最左侧或“最高有效位”(也称为“ {{3 }}“)。让我们考虑一下32位的情况。通过翻转符号位,然后将其传播到其他31个位位置,您将得到以下结果:

  • 对于正值和零,设置所有位(0xFFFFFFFF-1)或
  • 对于负值,将清除所有位(0x000000000)。

根据MSB的原始结果,您已经将该值归零,但前提是该值最初为负。

备注

  1. 由于在{strong> C#中&(按位- AND )的优先级很低,因此通常必须将这些表达式括起来带有外括号:

    ((~num >> 31) & num)
    
  2. 如果num unsigned (例如uint ui),则必须使用强制转换来确保班次已签名。这称为右算术移位,它可以确保将MSB复制到每个右移位置:

    ((int)~ui >> 31) & ui
    
  3. 对于64位值,请移位63位而不是31位:

    /* signed */     long v;      (~v >> 63) & v
    
    /* unsigned */   ulong ul;    ((long)~ul >> 63) & ul
    
  4. 如图所示,您必须使用~(按位- NOT )运算符来翻转符号位。如果尝试改用“一元减号” -,则将得到错误的答案0x80000000,因为这是不受加减号影响的两个整数值之一。 (另一个为零,但碰巧可以正常工作)。另一方面,按位- NOT 可以保证翻转任何/每个值的每一位。

  5. 如果您很着急,这里有一些经过测试的扩展方法,可以随时复制/粘贴:

    public static int Clamp0(this int v) => v & ~v >> 31;
    
    public static long Clamp0(this long v) => v & ~v >> 63;
    


了解有关非分支代码的更多信息!

上面提供的此代码示例是演示masking的最简单的bit-twiddling示例之一。如果您不熟悉它,那么该术语通常指的是各种各样的微优化技术,这些技术试图最小化用户代码中的条件分支,以减少CPU管道中的错误预测停顿。