ما هي أفضل طريقة لتمثيل System.Decimal في بروتوكول المخازن؟

StackOverflow https://stackoverflow.com/questions/371604

سؤال

وبعد يوم من هذا السؤال ، ما يمكن أن يكون أفضل طريقة لتمثيل كائن System.Decimal في مخزن البروتوكول؟

هل كانت مفيدة؟

المحلول

حسنا، سوف protobuf صافي ببساطة التعامل مع هذا بالنسبة لك. تشغيله من خصائص أنواع، ولها الدعم الكامل لdecimal. لأنه ليس هناك أي وسيلة مباشرة للتعبير عن decimal في بروتو، أنها لن (حاليا) توليد خاصية decimal من ملف ".proto"، ولكن سيكون من الجميل أن قرص التعرف على بعض نوع شائع ( "BCL.Decimal" أو ما شابه) وتفسر على أنها عشري.

وأما بالنسبة تمثل ذلك - كان لي ثيقة المناقشة على هذا (الآن للخروج من التاريخ وأظن) في منطقة يكي protobuf صافي. الآن هناك نسخة تعمل في protobuf صافي أن مجرد يفعل ذلك بالنسبة لك.

ومما لا شك فيه أن جون وأنا تدق من ذلك أكثر في وقت لاحق اليوم ؛-p

وإصدار protobuf الصافي من هذا (في .proto) هو شيء من هذا القبيل (من <لأ href = "http://code.google.com/p/protobuf-net/source/browse/trunk/Tools/bcl .proto "يختلط =" noreferrer "> هنا ):

message Decimal {
  optional uint64 lo = 1; // the first 64 bits of the underlying value
  optional uint32 hi = 2; // the last 32 bis of the underlying value
  optional sint32 signScale = 3; // the number of decimal digits, and the sign
}

نصائح أخرى

ومارك ولدي خطط غامضة للغاية من أجل التوصل إلى مكتبة "رسالة PB مشتركة" بحيث يمكنك تمثل الأنواع الشائعة جدا (التاريخ / الوقت وعشري في الظهور على الفور إلى الذهن) بطريقة مشتركة، مع التحويلات المتاحة في. NET وجافا (وأي شيء آخر أي شخص يريد أن يساهم).

إذا كنت راضيا التمسك .NET، وكنت تبحث عن الاكتناز، ويهمني أن تذهب ربما مع شيء من هذا القبيل:

message Decimal {

    // 96-bit mantissa broken into two chunks
    optional uint64 mantissa_msb = 1;
    optional uint32 mantissa_lsb = 2;

    required sint32 exponent_and_sign = 3;
}

ويمكن أن يكون مجرد تمثيل علامة من علامة exponent_and_sign، مع الأس يجري القيمة المطلقة.

وجعل كلا الجزأين من العشري اختياري يعني أن 0 يمثل <م> جدا مضغوط (ولكن لا يزال التفريق بين 0M و0.0000m الخ). exponent_and_sign يمكن أن يكون اختياريا، وكذلك إذا أردنا حقا.

وأنا لا أعرف عن المشروع مارك، ولكن في ميناء بلدي إنشاء فئات جزئية، حتى تتمكن من وضع التحويل بين System.Decimal وProtobuf.Common.Decimal (أو أيا كان) في فئة جزئية.

ولقد وضعت التصحيح لprotobuf-CSHARP الميناء مع هوكس الذي يولد الطبقات protobuf مع عشري الأصلي والبنيات التاريخ والوقت. شكل سلك الحكمة، تكون ممثلة من قبل اثنين من رسائل بروتو "المدمج".

وهنا هو الرابط: <وأ href = "https://code.google.com/p/protobuf-csharp-port/issues/detail؟can=2&start=0&num=100&q=&colspec=ID٪20Type٪20Status٪20Priority٪20Milestone٪20Owner٪20Summary&groupby = ونوع = & معرف = 78 "يختلط =" نوفولو "> https://code.google.com/p/protobuf-csharp-port/issues/detail؟can=2&start=0&num=100&q=&colspec=ID٪20Type٪20Status ٪ 20Priority٪ 20Milestone٪ 20Owner٪ 20Summary وgroupby = ونوع = & معرف = 78

وأبسط قليلا لتنفيذ النهج من جون مارك أو غير لتخزينه كما 4 القيم sint32، التي تقوم بتعيين ملائم بشكل مسلي لإخراج <لأ href = "https://docs.microsoft.com/en-us/dotnet /api/system.decimal.getbits؟view=netframework-4.8 "يختلط =" نوفولو noreferrer "> Decimal.GetBits () .

وسيقوم الملف بروتو تبدو:

message ProtoDecimal {
    sint32 v1 = 1;
    sint32 v2 = 2;
    sint32 v3 = 3;
    sint32 v4 = 4;
}

وتحويل سيكون:

public decimal ConvertToDecimal(AbideDecimal value)
{
    return new decimal(new int[] { value.V1, value.V2, value.V3, value.V4 });
}

public ProtoDecimal ConvertFromDecimal(decimal value)
{
    var bits = decimal.GetBits(value);
    return new ProtoDecimal 
    {
        V1 = bits[0],
        V2 = bits[1],
        V3 = bits[2],
        V4 = bits[3]
    }
}

وهذا قد لا يكون بهذه البساطة في لغات أخرى، ولكن إذا كان لديك فقط لاستهداف C # بعد ذلك سوف يستغرق نفس أقصى 16 بايت أن النهج الآخر سوف (على الرغم من قيم مثل 0 قد لا تكون مخزنة كما مضغوط - I لا أعرف ما يكفي عن التفاصيل المعقدة لكيفية protobuf مخازن [إينتس])، في حين يجري أكثر وضوحا للمبرمجين البكم البكم مثلي :)

ومن الواضح أن لديك ل سباق الخيول إذا تريد أداء اختبار ولكن أشك في أن هناك الكثير في ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top