代码之家  ›  专栏  ›  技术社区  ›  John Smith

从C#ushort中的某些位提取无符号值

  •  0
  • John Smith  · 技术社区  · 14 年前

    我需要一种从无符号短消息中的某些位提取值的好方法:

    ushort内部4个警报的定义:

    Name......Range.......Bits
    Alarm4....0-15....13/16-16/16
    Alarm3....0-15....9/16-12/16
    Alarm2....0-15....5/16-8/16
    Alarm1....0-15....1/16-4/16
    

    ushort的值:4383或(二进制的1000100011111)

    所以我想要实现的是:

    1001100110011001
    Alarm1.....Alarm2.....Alarm3......Alarm4
    1001.......1001.......1001........1001
    
    Gets translated into:
    Alarm1....Alarm2....Alarm3....Alarm4
    9............9............9............9
    

    使用伪代码:

    getValueFunc(ushort bits, int offset);  
    ushort u = 4383;
    UInt16 Alarm1Value = getValueFunc(u, 1);
    UInt16 Alarm2Value = getValueFunc(u, 5);
    UInt16 Alarm3Value = getValueFunc(u, 9);
    UInt16 Alarm4Value = getValueFunc(u, 13);
    

    当做, 约翰

    5 回复  |  直到 14 年前
        1
  •  4
  •   nothrow    14 年前
    int GetFromBits(ushort bits, int offset)
    {
     return (bits >> (offset - 1)) & 0xF;
    }
    
        2
  •  2
  •   Victor Haydin    14 年前
    bool GetBit(ushort bits, int offset) {
        return (bits & (1<<offset)) != 0;
    }
    
        3
  •  0
  •   Neil    14 年前

    除非有特殊的理由使用ushort,否则我强烈建议您使用 enum flags . 这是C#中按位操作的替代品。

        4
  •  0
  •   Aliostad    14 年前

    使用枚举:

    [Flags]
    public enum Alarm : int
    {
        AlarmValue1 = 0x1,
        AlarmValue2 = // the Hex Value,
        AlarmValue3 = // the Hex Value,
        AlarmValue4 = // the Hex Value
    
    }
    
    
    ushort myValue = 0x687;
    Alarm alarm = (Alarm) myValue;
    
    Console.WriteLine(alarm & AlarmValue3);
    
        5
  •  0
  •   dbasnett    14 年前

    使用枚举标志的VB示例

    Public Class Form1
    
        <FlagsAttribute()> _
        Public Enum Alarms As UShort
            'bits in short
            '1 1 1 1 1 1
            '5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
            No_Alarms = 0 'do not change
    
            Alarm1All = &HF
            HighTemp1 = 1 << 0
            LowOilPress1 = 1 << 1
            HighRPM1 = 1 << 2
            LowRPM1 = 1 << 3
    
            Alarm2All = &HF0 'alarm two is a 4 bit value 0 - 15
            _bit0AL2 = 1 << 4
            _bit1AL2 = 1 << 5
            _bit2AL2 = 1 << 6
            _bit3AL2 = 1 << 7
    
            Alarm3All = &HF00
            Cond3_0 = 1 << 8
            Cond3_1 = 1 << 9
            Cond3_2 = 1 << 10
            Cond3_3 = 1 << 11
    
            Alarm4All = &HF000
            DoorAjar = 1 << 12
            O2Sensor = 1 << 13
            LightsOn = 1 << 14
            LowFuel = 1 << 15
    
            All_Alarms = &HFFFF 'do not change
    
            zAlarm1Offs = 0US
            zAlarm2Offs = 4US
            zAlarm3Offs = 8US
            zAlarm4Offs = 12US
        End Enum
    
        Private Sub Button1_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) Handles Button1.Click
    
            Dim foo As Alarms = Alarms.No_Alarms 'set no alarms
            debugAlarm(foo)
    
            'turn some alarms on
            foo = Alarms.HighTemp1 Or Alarms.LowOilPress1
            debugAlarm(foo)
    
            'turn some more on
            foo = foo Or Alarms._bit0AL2 Or Alarms._bit3AL2 Or Alarms.Cond3_2 Or Alarms.Cond3_3 Or Alarms.LightsOn Or Alarms.LowFuel
            debugAlarm(foo)
    
            'check Alarm4
            If (foo And Alarms.Alarm4All) <> Alarms.No_Alarms Then 'any fours on
                'check which 4
                If (foo And Alarms.DoorAjar) = Alarms.DoorAjar Then
                    'Cond4_0 on
                    Stop
                ElseIf (foo And Alarms.O2Sensor) = Alarms.O2Sensor Then
                    'Cond4_1 on
                    Stop
                ElseIf (foo And Alarms.LightsOn) = Alarms.LightsOn Then
                    'Cond4_2 on
                    foo = foo And (Alarms.All_Alarms Xor Alarms.LightsOn) 'turn off Cond4_2
                ElseIf (foo And Alarms.LowFuel) = Alarms.LowFuel Then
                    'Cond4_3 on
                    Stop
                End If
            End If
            debugAlarm(foo)
    
            'check Alarm2 
            If (foo And Alarms.Alarm2All) <> Alarms.No_Alarms Then 'any twos on
                'check Alarm2 for values
                Select Case CUShort(foo And Alarms.Alarm2All) 'foo And Alarms.Alarm2All
                    Case 1US << Alarms.zAlarm2Offs 'Alarms._bit0AL2
                        Stop
                    Case 2US << Alarms.zAlarm2Offs 'Alarms._bit1AL2
                        Stop
                    Case 3US << Alarms.zAlarm2Offs 'Alarms._bit0AL2 or Alarms._bit2AL2
                        Stop
                    Case 4US << Alarms.zAlarm2Offs
                        Stop
                    Case 5US << Alarms.zAlarm2Offs
                        Stop
                    Case 6US << Alarms.zAlarm2Offs
                        Stop
                    Case 7US << Alarms.zAlarm2Offs
                        Stop
                    Case 8US << Alarms.zAlarm2Offs
                        Stop
                    Case 9US << Alarms.zAlarm2Offs
                        debugAlarm(foo And Alarms.Alarm2All)
                        Stop
                    Case 10US << Alarms.zAlarm2Offs
                        Stop
                    Case 11US << Alarms.zAlarm2Offs
                        Stop
                    Case 12US << Alarms.zAlarm2Offs
                        Stop
                    Case 13US << Alarms.zAlarm2Offs
                        Stop
                    Case 14US << Alarms.zAlarm2Offs
                        Stop
                    Case 15US << Alarms.zAlarm2Offs
                        Stop
                End Select
            End If
            debugAlarm(foo)
    
        End Sub
    
        Private Sub debugAlarm(ByVal _alarm As Alarms)
            Debug.WriteLine("")
            Dim asUshort As UShort = _alarm
            Debug.WriteLine(_alarm.ToString)
            Debug.WriteLine(Convert.ToString(asUshort, 2).PadLeft(16, "0"c))
        End Sub
    End Class