在协议缓冲区中表示System.Decimal的最佳方法是什么?

时间:2008-12-16 15:09:31

标签: c# .net floating-point protocol-buffers

this问题后,在协议缓冲区中表示System.Decimal对象的最佳方法是什么?

5 个答案:

答案 0 :(得分:7)

好吧,protobuf-net将为您处理这个问题;它运行类型的属性,并完全支持decimal。由于没有直接的方法在proto中表达decimal,因此它不会(当前)从“.proto”文件生成decimal属性,但是识别一些常见内容将是一个很好的调整输入(“BCL.Decimal”或类似)并将其解释为十进制。

至于代表它 - 我在protobuf-net wiki区域有一个discussion document(我怀疑已经过时了);现在有一个protobuf-net的工作版本,它只是为你做的。

毫无疑问,乔恩和我今天晚些时候会更多地解决这个问题;-p

这个(在.proto中)的protobuf-net版本就像(来自here):

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
}

答案 1 :(得分:5)

Marc和我有一个非常模糊的计划,想出一个“常见的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表示非常紧凑(但仍然区分0m和0.0000m等)。如果我们真的想要,exponent_and_sign也可以是可选的。

我不知道Marc的项目,但是在我的端口中我生成了部分类,所以你可以将System.Decimal和Protobuf.Common.Decimal(或其他)之间的转换放入部分类中。

答案 2 :(得分:0)

我为protobuf-csharp-port添加了一个带有钩子的补丁,它使用原生的Decimal和DateTime结构生成protobuf类。有线格式,它们由两个“内置”原型消息代表。

这是链接: 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

答案 3 :(得分:0)

比Jon或Marc的实现方法更简单的方法是将其存储为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如何存储int的复杂细节知之甚少,而对于像我这样的傻瓜程序员来说却要清晰得多:)

很显然,如果要测试性能,则必须race the horses,但我怀疑其中是否有很多内容。

答案 4 :(得分:0)

当您知道小数位数有限时,可以使用最小的单位作为整数值。例如,在处理货币时,不需要十进制类型,而是可以定义使用单位美分。然后,无论使用哪种货币,值均为2的整数都将引用0.02