Каков наилучший способ представления System.Десятичное число в буферах протокола?

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

Вопрос

Следуя дальше от это вопрос, каков наилучший способ представления System.Десятичный объект в буфере протокола?

Это было полезно?

Решение

Что ж, protobuf-net просто справится с этим за вас;он использует свойства типов и имеет полную поддержку decimal.Поскольку нет прямого способа выразить decimal в proto он не будет (в настоящее время) генерировать decimal свойство из файла ".proto", но было бы неплохо настроить распознавание некоторого общего типа ("BCL.Decimal" или аналогичного) и интерпретировать его как десятичный.

Что касается представления этого - у меня был дискуссионный документ об этом (как я подозреваю, уже устаревшем) в вики-разделе protobuf-net;теперь в protobuf-net есть рабочая версия, которая просто делает это за вас.

Без сомнения, мы с Джоном обсудим это позже сегодня ;-p

Версия protobuf-net этого (в .proto) выглядит примерно так (из здесь):

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
}

Другие советы

У нас с Марком есть очень смутные планы создать библиотеку "common PB message", такую, чтобы вы могли представлять довольно распространенные типы (дата / время и десятичная дробь, мгновенно приходящие на ум) обычным способом, с преобразованиями, доступными в .NET и Java (и все остальное, что кто-либо захочет внести).

Если вы с удовольствием придерживаетесь .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 очень компактно (но все еще различаясь между 0 м и 0,0000 м и т.д.).exponent_and_sign также мог бы быть необязательным, если бы мы действительно захотели.

Я не знаю о проекте Марка, но в моем порту я генерирую частичные классы, так что вы можете выполнить преобразование между System.Decimal и Protobuf.Обычный.Decimal (или что-то еще) в частичный класс.

Я собрал патч для protobuf-csharp-port с перехватами, который генерирует классы protobuf с собственными структурами Decimal и DateTime.С точки зрения проводного формата, они представлены двумя "встроенными" протосообщениями.

Вот ссылка: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=&sort=&id=78

Немного более простой в реализации подход, чем у Джона или Марка, заключается в сохранении его как 4 sint32 значения, которые удобно тривиально сопоставляются с выводом Десятичный.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 могут храниться не так компактно - я недостаточно разбираюсь в сложных деталях того, как protobuf хранит целые числа), и при этом будет намного понятнее для тупых программистов вроде меня :)

Очевидно, вам придется участвуйте в гонках на лошадях если вы хотите протестировать производительность, но я сомневаюсь, что в этом много чего есть.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top