You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中多值编码为64位long的位操作实现咨询

How to Encode Multiple Values into a 64-bit long in C#

Hey there! Let's walk through how to pack your date/time values (and extra data) into a single long—bitwise operations might seem intimidating at first, but they're straightforward once you grasp the basics of shifting and masking.

First, Let's Lock in the Bit Layout

You specified a total of 63 bits to use (we'll leave the 64th bit empty to avoid signed integer headaches). Here's the fixed structure we'll implement:

  • Year: 12 bits (covers 0–4095, easily handles your max of 2048) → occupies bits 51–62 (counting from 0 as the lowest bit)
  • Month: 6 bits (0–63, fits your max of 16) → occupies bits 45–50
  • Day: 7 bits (0–127, handles your max of 32) → occupies bits 38–44
  • Hour: 7 bits (0–127, fits your max of 32) → occupies bits 31–37
  • Extra Data: 31 bits (for any additional values you might need later) → occupies bits 0–30

Core Bitwise Concepts to Know

We'll use three simple operations to make this work:

  1. Left Shift (<<): Moves a number's bits to the left by a set number of positions, padding with zeros. This lets us "slot" each value into its designated spot in the long.
  2. Bitwise OR (|): Merges numbers by setting a bit to 1 if it's 1 in either value. We use this to combine all shifted values into one long.
  3. Bitwise AND (&): Extracts specific bits by masking out the rest. This is how we pull individual values back out during decoding.

Encoding Function

This function takes your values, validates they fit their bit ranges, and packs them into a single long:

public static long EncodeFields(int year, int month, int day, int hour, long extraData = 0)
{
    // Validate inputs to prevent overflow into other fields
    if (year is < 0 or > 4095)
        throw new ArgumentOutOfRangeException(nameof(year), "Year must be between 0 and 4095");
    if (month is < 0 or > 63)
        throw new ArgumentOutOfRangeException(nameof(month), "Month must be between 0 and 63");
    if (day is < 0 or > 127)
        throw new ArgumentOutOfRangeException(nameof(day), "Day must be between 0 and 127");
    if (hour is < 0 or > 127)
        throw new ArgumentOutOfRangeException(nameof(hour), "Hour must be between 0 and 127");
    if ((extraData & ~0x7FFFFFFFL) != 0)
        throw new ArgumentOutOfRangeException(nameof(extraData), "Extra data must fit in 31 bits");

    long encodedValue = 0;

    // Shift each value to its position and merge with OR
    encodedValue |= (long)year << 51;
    encodedValue |= (long)month << 45;
    encodedValue |= (long)day << 38;
    encodedValue |= (long)hour << 31;
    encodedValue |= extraData & 0x7FFFFFFFL; // Keep only the first 31 bits of extra data

    return encodedValue;
}

Decoding Function

This function takes the encoded long and extracts each original value using masking and shifting:

public static void DecodeFields(long encodedValue, out int year, out int month, out int day, out int hour, out long extraData)
{
    // Mask and shift to pull out each field
    year = (int)((encodedValue >> 51) & 0xFFFL); // 0xFFF = 12 bits of 1s
    month = (int)((encodedValue >> 45) & 0x3FL); // 0x3F = 6 bits of 1s
    day = (int)((encodedValue >> 38) & 0x7FL);   // 0x7F = 7 bits of 1s
    hour = (int)((encodedValue >> 31) & 0x7FL);  // Same mask as day
    extraData = encodedValue & 0x7FFFFFFFL;      // Extract the first 31 bits
}

Test It Out!

Here's a quick example to see how it works in practice:

// Sample input values
int testYear = 2023;
int testMonth = 10;
int testDay = 25;
int testHour = 14;
long testExtraData = 123456;

// Encode the values
long encoded = EncodeFields(testYear, testMonth, testDay, testHour, testExtraData);
Console.WriteLine($"Encoded value: {encoded}");

// Decode them back
DecodeFields(encoded, out int decodedYear, out int decodedMonth, out int decodedDay, out int decodedHour, out long decodedExtra);
Console.WriteLine($"Decoded Values: Year={decodedYear}, Month={decodedMonth}, Day={decodedDay}, Hour={decodedHour}, Extra={decodedExtra}");

Key Notes

  • We left the 64th bit unused because long is a signed integer—using this bit could create negative values that break decoding.
  • The validation checks are critical to stop one field from spilling into another (e.g., a year larger than 4095 would overwrite the month bits).
  • If you need to add more fields later, just adjust the bit positions and update the encode/decode functions—just make sure total bits stay under 63.

内容的提问来源于stack exchange,提问作者LadislavBohm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:03:42