Pregunta

A raíz de esta pregunta , ¿cuál sería la mejor manera de representar un objeto System.Decimal en un búfer de protocolo?

¿Fue útil?

Solución

Bueno, protobuf-net simplemente se encargará de esto para usted; Se ejecuta fuera de las propiedades de los tipos, y tiene soporte completo para decimal. Puesto que no hay una forma directa de expresar <=> en proto, no va (en la actualidad) generar una propiedad <=> desde un archivo "Proto", pero sería un buen pellizco de reconocer algún tipo común ( "BCL .Decimal" o similar) e interpretarla como decimal.

En cuanto a representarla - tuve una documento de discusión en este (ahora fuera de fecha sospecho) en la zona wiki-protobuf red; ahora hay una versión de trabajo en protobuf-red que simplemente lo hace por usted.

No hay duda de Jon y yo martillarán esto más tarde hoy -P

La versión de protobuf neto de esto (en .proto) es algo así como (de aquí ):

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
}

Otros consejos

Marc y tengo planes muy vagas de subir con una biblioteca "mensaje PB común" de tal manera que se puede representar tipos muy comunes (fecha / hora y decimales que salte inmediatamente a la mente) de una manera común, con las conversiones disponibles en. NET y Java (y cualquier otra cosa que nadie quiere contribuir).

Si estás dispuesto a pegarse a .NET, y que está buscando para compacidad, me gustaría ir posiblemente con algo como:

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;
}

El signo solo puede ser representado por el signo de exponent_and_sign, con el exponente siendo el valor absoluto.

Realización de las dos partes de la mantisa opcional 0 significa que está representado muy de forma compacta (pero aún así la diferenciación entre 0m y 0.0000m etc). exponent_and_sign podría ser opcional y si realmente queríamos.

No sé sobre el proyecto de Marc, pero en mi puerto genero clases parciales, por lo que puede poner la conversión entre un System.Decimal y Protobuf.Common.Decimal (o lo que sea) en la clase parcial.

Monté un parche para protobuf-CSharp puertos con ganchos que genera las clases protobuf con decimal nativa y estructuras DateTime. Formato de alambre sabia, que están representados por dos mensajes proto "built-in".

Aquí está el enlace: 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 y GroupBy = & sort = & id = 78

Un poco más sencillo de implementar el enfoque de Jon o Marc es almacenarlo como 4 sint32 valores, que convenientemente mapas trivialmente a la salida de Decimal.GetBits () .

El archivo proto se verá así:

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

Y el convertidor será:

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]
    }
}

Esto podría no ser tan simple en otros idiomas, pero si sólo tiene que dirigirse a C # y luego tomará hasta el mismo máximo de 16 bytes que (aunque no se almacene como se compacta el otro enfoque valores como 0 - I no se sabe lo suficiente sobre los intrincados detalles de cómo protobuf almacena enteros), mientras que es mucho más claro para los programadores tonto-tonto como yo :)

Obviamente, tendrá que correr los caballos si quieres rendimiento de la prueba pero dudo que hay mucho en ella.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top