在概念上类似于Math.Abs() - 我正在寻找一个函数,当给定正整数时将返回相同的整数。如果给出否定,则返回零。
所以:
f(3) = 3
f(0) = 0
f(-3) = 0
是的,这很简单,我自己写,但我想知道.NET Math类是否已经内置了这个内容,或者是否可以通过巧妙地链接一些Math。*调用来实现相同的目标?
答案 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
)或0x00000000
,0
)。 根据MSB的原始结果,您已经将该值归零,但前提是该值最初为负。
备注
由于在{strong> C#中&
(按位- AND
)的优先级很低,因此通常必须将这些表达式括起来带有外括号:
((~num >> 31) & num)
如果num
是 unsigned (例如uint ui
),则必须使用强制转换来确保班次已签名。这称为右算术移位,它可以确保将MSB复制到每个右移位置:
((int)~ui >> 31) & ui
对于64位值,请移位63位而不是31位:
/* signed */ long v; (~v >> 63) & v
/* unsigned */ ulong ul; ((long)~ul >> 63) & ul
如图所示,您必须使用~
(按位- NOT
)运算符来翻转符号位。如果尝试改用“一元减号” -
,则将得到错误的答案0x80000000
,因为这是不受加减号影响的两个整数值之一。 (另一个为零,但碰巧可以正常工作)。另一方面,按位- NOT
可以保证翻转任何/每个值的每一位。
如果您很着急,这里有一些经过测试的扩展方法,可以随时复制/粘贴:
public static int Clamp0(this int v) => v & ~v >> 31;
public static long Clamp0(this long v) => v & ~v >> 63;
了解有关非分支代码的更多信息!
上面提供的此代码示例是演示masking的最简单的bit-twiddling示例之一。如果您不熟悉它,那么该术语通常指的是各种各样的微优化技术,这些技术试图最小化用户代码中的条件分支,以减少CPU管道中的错误预测停顿。