获取给定父节点的子节点

本文关键字:子节点 父节点 获取 | 更新日期: 2023-09-27 18:17:23

我有一组数字:1、2、4、8、16、32、64等。

现在给定一个数字,比如44,我必须确定它有32 8和4个子数。(32 + 8 + 4 = 14)

到目前为止,我得到的是以下代码:
   public static long[] GetBTreeChildren(long? parentMask)
    {            
        var branches = new List<long>();
        if (parentMask == null) return branches.ToArray();
        double currentValue = (double)parentMask;            
        while (currentValue > 0D)
        {
            double power = Math.Floor(Math.Log(currentValue, 2.0D));
            double exponentResult = Math.Pow(2, power);
            branches.Add((long)exponentResult);
            currentValue -= exponentResult;
        }
        return branches.ToArray();
    }

但是当给定的数字非常大(例如36028797018963967)时,上面的代码不起作用

我正在使用VS2012 (c#)。

获取给定父节点的子节点

对于非常大的数字不起作用的原因是因为您使用的是double数据类型,它在精度上是有限的(大约16位)。

代替使用Math.PowMath.Log,您所需要的一切都可以通过简单,极其有效的按位操作来完成。

public static long[] GetBTreeChildren(long? parentMask)
{            
    var branches = new List<long>();
    if (parentMask == null) return branches.ToArray();
    for(int i = 0; i < 63; ++i)
    {
        if( (parentMask & (1L << i)) != 0)
            branches.Add(1L << i);
    }            
    return branches.ToArray();
}

基本上,每个位已经是2的幂,这就是你要找的。通过(long) 1 << i,你把第一位移到2的i次方。您可以调整上面的代码,使其更类似于您的代码,并且稍微更高效,而不是在i上迭代,只需将parentMask的位向右移动,但是您必须意识到负数会发生什么,以及逻辑移位与算术移位的区别。