c# - 需要一个先升后降的快速函数,使用按位运算

标签 c# bit-manipulation

我需要一个整数值函数,它返回一个升序序列,直到达到给定的最大值,然后再次下降。我称之为通灵塔:

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/

相关文章:

c# - 如何将 JSON 中的键值对更改为 XML 属性而不是节点

c# - 什么时候抛出异常更好,什么时候返回一些错误日志 'object' 更好?

c# - 如何添加调试代码? (应该去Debug,不应该去Release)

c# - 将两个 if 合二为一

c - 带溢出校正的按位乘法

c# - 我可以将 html 或 css 类添加到 @Html.DropDownListFor 元素吗

c# - aspose.word 仅返回第一个表和部分

c - C中的char数组内的位交换

c - 高效地对 int 数组进行位移?

c - 旋转由字节数组表示的位图