19

这个问题开始,在协议缓冲区中表示 System.Decimal 对象的最佳方式是什么?

4

5 回答 5

8

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

至于表示它——我在 protobuf-net wiki 区域有一个关于这个的讨论文件(我怀疑现在已经过时了);现在 protobuf-net 中有一个工作版本,可以为您简单地完成它。

毫无疑问,乔恩和我将在今天晚些时候更进一步地解决这个问题;-p

这个(在 .proto 中)的 protobuf-net 版本类似于(从这里):

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
}
于 2008-12-16T16:36:51.097 回答
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(或其他)之间的转换放入部分类中。

于 2008-12-16T15:47:15.283 回答
1

一种比 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 的复杂细节有足够的了解),同时对像我这样的愚蠢的程序员来说更清楚:)

显然,如果您想测试性能,您将不得不与马匹比赛,但我怀疑其中有很多。

于 2019-06-11T21:24:14.627 回答
1

当您知道小数位数有限时,您可以使用可能的最小单位作为整数值。例如,在处理货币时,不需要小数类型,而是可以定义为使用单位美分。然后一个具有值的整数2将引用0.02任何使用的货币。

于 2019-10-20T23:17:13.520 回答
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 =&排序=&id=78

于 2014-02-25T00:51:53.233 回答