我需要一个整数值函数,它返回一个升序,直到它达到给定的最大值,然后再次下降。我称它为Ziggurat:
0 1 2 3 4 5 6 6 5 4 3 2 1 0
步骤都是一个。最大值(在序列的中间)必须出现两次。在零到最大 2* 的范围之外,我不在乎会发生什么。
我希望函数快速 - 没有分支。我更喜欢按位运算。
作为一个不起作用的例子,这是我的 Pyramid 函数,以及我的绝对值实现:
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();
}
这个 Pyramid 函数创建像 0 1 2 3 4 5 6 5 4 3 2 1 0 这样的序列
请注意,中间的数字只出现一次。
我有一个想法,将查找表存储为 long 或 BigInteger 中的连续位块,并将它们移位和屏蔽掉,但这对于长系列来说占用了太多内存。不过,它使用的指令很少。