我需要一个整数值函数,它返回一个升序序列,直到达到给定的最大值,然后再次下降。我称之为通灵塔:
0 1 2 3 4 5 6 6 5 4 3 2 1 0
一步一个脚印。最大值(在序列的中间)必须出现两次。在 0 到 2* max 范围之外,我不在乎会发生什么。
我希望函数快速 - 没有分支。我更喜欢按位运算。
作为不起作用的示例,这是我的金字塔函数,以及我对绝对值的实现:
private static readonly int LONG_ABS_MASK_SHIFT = sizeof(long) * 8 - 1;
/// <summary>
/// Compute the Absolute value of a long without branching.
///
/// Note: This will deviate from Math.Abs for Int64.MinValue, where the .NET library would throw an exception.
/// The most negative number cannot be made positive.
/// </summary>
/// <param name="v">Number to transform.</param>
/// <returns>Absolute value of v.</returns>
public static long Abs(this long v)
{
long mask = v >> LONG_ABS_MASK_SHIFT;
return (v ^ mask) - mask;
}
public static long Pyramid(this long N, long max)
{
return max - (max - N).Abs();
}
这个金字塔函数创建了类似 0 1 2 3 4 5 6 5 4 3 2 1 0 的序列
注意中间的数字只出现一次。
我有一个想法,将查找表存储为 long 或 BigInteger 中的连续位 block ,然后将它们移位和屏蔽掉,但是对于长系列来说,这会占用太多内存。不过,它使用的指令很少。
最佳答案
试试这个:
public static long Pyramid2(this long N, long max)
{
return N.Pyramid(max + 1) + ((max - N) >> -1);
}
结果:
0 1个 2个 3个 4个 5个 6个 6个 5个 4个 3个 2个 1个 0
得到结果如下:
\ N=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
N.Pyramid(6 + 1) 0 1 2 3 4 5 6 7 6 5 4 3 2 1 0 -1 -2 -3 -4
+ ((max - N) >> -1) 0 0 0 0 0 0 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
= 0 1 2 3 4 5 6 6 5 4 3 2 1 0 -1 -2 -3 -4 -5
Pyramid 是问题中定义的原始 Pyramid 方法。
关于c# - 需要一个先升后降的快速函数,使用按位运算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10098949/