从Python十进制填充协议缓冲区的两倍

时间:2018-12-12 08:57:39

标签: python floating-point protocol-buffers precision

TL,DR; 如何将Python十进制。十进制的实例写入协议缓冲区double字段?

详细信息; 在Python协议缓冲区中,scalar message field可以是double

给出Python的decimal.Decimal类的实例:

# Intentionally high-precision number.
d = Decimal(3.14159265358979323846264)

...和Protocol Buffer定义:

message Test {
  double value = 1;
}

我想尝试填充Test.value

d = Decimal(3.14159265358979323846264)

try:
  my_proto_pb2.Test(value=d)
except ValueError:
  # Could not store in a `double`.

如预期的那样,这将引发TypeError。请注意,我正在exceptValueError,因为这是Python ProtoBuffer type_checkers.py模块引发的。我想要一个ValueError。我TypeError:)

TypeError: 
Decimal('3.14159265358979323846264') 
has type <class 'decimal.Decimal'>,
but expected one of: ((<class 'numbers.Real'>,),) for field Test.value

我希望这样做,但是将Decimal转换为float会导致在填充原型之前的精度下降:

d = Decimal(3.14159265358979323846264)

try:
  my_proto_pb2.Test(value=float(d))
except ValueError:
  # Could not store in a `double`.

没有TypeError,但是Test.value拥有3.141592653589793

协议缓冲区的Python实现使用TypeChecker来确定类型和值是否兼容。参见google/protobuf/internal/type_checkers.py。但是,只有以下检查程序:

  • IntValueChecker
  • EnumValueChecker
  • UnicodeValueChecker
  • Int32ValueChecker
  • Uint32ValueChecker
  • Int64ValueChecker
  • Uint64ValueChecker

因此,以下代码适用于非常大的整数,因为Int64ValueChecker会引发ValueError

message AnotherTest {
  int64 value = 1;
}

...以及相应的Python:

n = 18446744073709551616
try:
  value = my_proto.AnotherTest(value=int(n))
except ValueError:
  # Could not store in a `int64`.

0 个答案:

没有答案