【问题标题】:Back and forth calculation of integer Identifier using bit shifting and OR operations使用位移和 OR 运算来回计算整数标识符
【发布时间】:2015-03-11 06:56:56
【问题描述】:

早上好,不知道这个问题是否涉及到正确的 StackExchange 网络。如果不是请见谅。

我得到了一个十进制/整数标识符值,我需要将其拆分为三个单独的值。假设我们有程序 ABC。程序 ABC 正在使用以下公式生成十进制/整数标识符值:

int identifier = 0;
int unitTypeId = 1;
int boardId = 4;
int messageId = 20;

identifier = (((unitTypeId) << 8) | ((boardId) << 5) | (messageId));

identifier 现在包含一个基于位移和 OR 运算的值。

现在我们必须开发 Program CDE。程序 CDE 读出一个日志文件,其中包含十进制/整数标识符和一些其他值,这些值在这种情况下不是必需的。程序 CDE 必须将读取标识符拆分为三个值:

int unitTypeId = 1;
int boardId = 4;
int messageId = 20;

第一:有没有办法做到这一点?

我的第一次尝试看起来像这样,但老实说,我没有得到标识符所基于的原始值。

private void resolveIdentifier()
{
    this.IdentifierBits = Convert.ToString(this.OriginIdentifier, 2); //Convert to binary in a string

    // Message identifiers are constructed:         
    // Unit Type                    Bit 8-10
    // Board ID                     Bit 5-7
    // Unit Specific Message Ids    Bit 0-4

    int[] bits = this.IdentifierBits.PadLeft(11, '0') // Add 0's from left
                     .Select(c => int.Parse(c.ToString())) // convert each char to int
                     .ToArray(); // Convert IEnumerable from select to Array

    Array.Reverse(bits);

    for (int i = 0; i < bits.Length; i++)
    {
        int calcValue = i;
        if (i < 5) // Message Id
        {
            this.MessageId += (int)Math.Pow(2, calcValue);
        }
        else if (i > 4 && i < 8)
        {
            calcValue -= 5;
            this.BoardId += (int)Math.Pow(2, calcValue);
        }
        else
        {
            calcValue -= 8;
            this.Unit += (int)Math.Pow(2, calcValue);
        }
    }
}

谁能告诉我我做错了什么以及是否有可能达到原始三个值?

【问题讨论】:

    标签: c# .net bit-manipulation bit


    【解决方案1】:

    只是掩码和移位。您已经收到了描述格式的评论:

    // Message identifiers are constructed:         
    // Unit Type                    Bit 8-10
    // Board ID                     Bit 5-7
    // Unit Specific Message Ids    Bit 0-4
    

    所以反转码是:

    int messageId = identifier & 0x1f;
    int boardId = (identifier >> 5) & 7;
    int unitType = (identifier >> 8) & 7;
    

    这里的 0x1f 是二进制的 11111 - 所以“与”只剩下底部的 5 位。 7 是二进制的 111 - 所以“与”只剩下底部的 3 位,这是您在稍微移动值后从 identifierboardIdunitType 想要的。

    如果您仍然对它的工作原理感到有些困惑,我建议您在纸上尝试一些值,以二进制形式显示所有内容 - 从消息 ID、板 ID 和单元类型开始,构建您的标识符(可能在数字的不同部分),然后看看当您应用上述移位/屏蔽时会发生什么。

    【讨论】:

    • 谢谢,成功了。是的,我有点困惑,但我会做纸上的把戏!
    猜你喜欢
    • 1970-01-01
    • 2020-01-20
    • 1970-01-01
    • 2020-12-17
    • 2012-09-19
    • 1970-01-01
    • 2015-07-08
    • 2014-09-08
    • 1970-01-01
    相关资源
    最近更新 更多