Skip to content

מספרים עשרוניים ובתים בסדר little-endian: קודם מגדירים פורמט

Original English article

איור המלווה את המאמר על סידור בתים בהמרת מספרים

מספרים עשרוניים ובתים בסדר little-endian: קודם מגדירים פורמט

המאמר המקורי מכנה המרת בתים מותאמת ״Clock & Data״, אך אינו מציין דגם קורא או מפרט פרוטוקול. המרת סדר בתים לבדה אינה מוכיחה תאימות ל־RFID, ל־NFC, ל־Wiegand או לממשק חשמלי של שעון ונתונים. לפני שימוש בכל ממיר עם חומרה, יש להשיג את תיעוד ההתקן המדויק ואת וקטורי הבתים הידועים שלו. כאן מוגדר במקום זאת פורמט יישומי מפורש עבור decimal של .NET.

אין כאן טענה שבוצע שילוב עם קורא כרטיסים או שהקוד הורץ. הסיפור בגוף ראשון ופלט המסוף במקור לא אומתו באופן עצמאי. הקוד החלופי הוא המחשה שלא הורצה, עבור .NET 8 ומעלה, ולא מנהל התקן.

משמעות הסיביות

מספר decimal ב־.NET כולל מקדם שלם בן 96 סיביות ומידע על סימן וקנה מידה. decimal.GetBits מחזירה ארבעה שלמים בני 32 סיביות: החלק הנמוך, האמצעי, הגבוה ואז הדגלים. השלם האחרון אינו מילה נוספת של המקדם. קנה המידה חייב להיות בין 0 ל־28, והסיביות השמורות חייבות להיות אפס. ראו את תיעוד Microsoft לייצוג decimal.

עבור המספר השלם 12345678, הייצוג בארבעה בתים בסדר big-endian הוא 00BC614E; רצף הבתים בסדר little-endian הוא 4E61BC00. ההסבר המקורי הפך את השמות. כמו כן, 20 תווים הקסדצימליים מייצגים 10 בתים, ולא 5 בתים או 160 סיביות.

קידוד ופענוח של פורמט מוגדר בן 16 בתים

הפורמט המקומי הבא כותב כל אחד מארבעת השלמים בסדר little-endian, בלי להסיר אפסים ובלי לחתוך את המילה הגבוהה של המקדם. התוצאה היא תמיד 16 בתים, המוצגים כ־32 תווים הקסדצימליים. זהו תחליף מכוון לשגרה המקורית בעלת הרוחב המשתנה, והוא אינו תואם לפורמט שלה ברמת הבתים. שני הצדדים חייבים להסכים לפורמט הזה.

using System;
using System.Buffers.Binary;
using System.Globalization;

public static class DecimalLittleEndian
{
    // Application-specific format: four Int32 values, each little-endian.
    // Order: low 32 bits, middle 32 bits, high 32 bits, sign/scale flags.
    public static string Encode(string text)
    {
        ArgumentNullException.ThrowIfNull(text);
        if (!decimal.TryParse(text,
            NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint,
            CultureInfo.InvariantCulture, out decimal value))
            throw new FormatException("Expected an invariant decimal value.");

        int[] parts = decimal.GetBits(value);
        byte[] bytes = new byte[16];
        for (int i = 0; i < 4; i++)
            BinaryPrimitives.WriteInt32LittleEndian(bytes.AsSpan(i * 4, 4), parts[i]);
        return Convert.ToHexString(bytes);
    }

    public static string Decode(string hex)
    {
        ArgumentNullException.ThrowIfNull(hex);
        if (hex.Length != 32)
            throw new FormatException("Expected exactly 32 hex characters.");
        byte[] bytes = Convert.FromHexString(hex);
        int[] parts = new int[4];
        for (int i = 0; i < 4; i++)
            parts[i] = BinaryPrimitives.ReadInt32LittleEndian(bytes.AsSpan(i * 4, 4));
        // The constructor rejects invalid reserved bits or scale values.
        return new decimal(parts).ToString(CultureInfo.InvariantCulture);
    }
}

ממשקי ה־API מגדירים במפורש את סדר הבתים: WriteInt32LittleEndian ו־ReadInt32LittleEndian. המתודה FromHexString דוחה קלט הקסדצימלי לא תקין.

תוכנית אימות ומקרי קצה

  • בפורמט המוגדר הזה, אפס שלם הוא 16 בתים של אפסים; הוא לעולם אינו מחרוזת ריקה.
  • עבור 12345678 השלם בקנה מידה אפס, הווקטור המתמטי הצפוי הוא 4E61BC00000000000000000000000000. זהו וקטור שחושב לפי ההגדרה, ולא פלט שנצפה בהרצה.
  • יש לבדוק ערכים חיוביים ושליליים, שברים, גבולות decimal, כל ערכי קנה המידה המותרים, תווים שגויים, אורך שגוי ודגלים לא תקינים. שוויון מספרי לאחר המרה הלוך ושוב אינו מוכיח לבדו תאימות לחומרה או עיצוב טקסט זהה.
  • המפענח מקבל במכוון סימן ונקודה עשרונית לפי תרבות בלתי תלויה, ולא פסיקים מקומיים, מפרידי אלפים או רווחים שרירותיים. המרה לטקסט אינה חייבת לשמר כל אופן כתיבה מקורי של המספר.
  • הרוחבים המשתנים, הסרת האפסים והשחזור החסר של הסיביות הגבוהות באלגוריתם המקורי אינם מתוקנים באמצעות ריפוד של דוגמה אחת. יש לשמור מטעני נתונים ישנים ולכתוב בדיקות הגירה מפורשות לפני החלפת פורמט שכבר נפרס.

סיכום

יש להבחין בין סדר הבתים של מספר שלם לבין פרוטוקול העברה שלם. השתמשו בייצוג מתועד ברוחב קבוע לנתוני היישום, ואמתו סריאליזציה ייעודית לחומרה מול המפרט האמיתי של היצרן, ולא לפי כותרת כגון ״Clock & Data״.

Post a Comment

Previous Post Next Post