Каков наилучший способ представления System.Decimal в буферах протокола? - PullRequest
12 голосов
/ 16 декабря 2008

Исходя из этого вопроса, как лучше всего представить объект System.Decimal в буфере протокола?

Ответы [ 4 ]

7 голосов
/ 16 декабря 2008

Ну, protobuf-net просто справится с этим; он запускает свойства типов и полностью поддерживает decimal. Поскольку в прото не существует прямого способа выражения decimal, он не будет (в настоящее время) генерировать свойство 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
}
5 голосов
/ 16 декабря 2008

У Марка и меня очень смутные планы создать библиотеку «общих сообщений PB», чтобы вы могли представлять довольно распространенные типы (дата / время и мгновенно возникающие десятичные числа) в общем виде, с преобразованиями, доступными в. 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.Common.Decimal (или любым другим) в частичный класс.

0 голосов
/ 12 июня 2019

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

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

0 голосов
/ 25 февраля 2014

Я собрал патч для 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

...