简体   繁体   English

Python cbor2 以首选(高效)格式编码浮点数

[英]Python cbor2 encode float in preferred (efficient) format

The CBOR docs state that the most efficient (less number of bytes) encoding should be preferred. CBOR 文档 state 应该首选最有效(字节数较少)的编码。

floats can be encoded as 64-bit floats, or with extensions as 32-bit, 16-bit, BigFloat or DecimalFloat formats.浮点数可以编码为 64 位浮点数,或扩展为 32 位、16 位、BigFloat 或 DecimalFloat 格式。

Stanards 64-bit encoding uses 9 bytes.标准 64 位编码使用 9 个字节。 Some floating values can take much less space if using an alterantive format (eg the values 0.0, 1.0, 1.5 can be represented as 4 bytes using BigFloats).如果使用替代格式,一些浮点值可以占用更少的空间(例如,值 0.0、1.0、1.5 可以使用 BigFloats 表示为 4 个字节)。

Some values are better represented as standard floats (eg 0.123456789 is represented by 9 bytes as 64-bit float or 29 bytes with BigFloats.有些值更好地表示为标准浮点数(例如 0.123456789 由 9 个字节表示为 64 位浮点数或 29 个字节与 BigFloats。

The cbor2 python library supports BigFloats if using the Decimal type, or the float if using the float type.如果使用Decimal类型, cbor2 python 库支持 BigFloats,如果使用float类型,则支持 float。

How can I get cbor2 to automatically emit the most efficient type depending on the actual value?如何让cbor2根据实际值自动发出最有效的类型?

I have tried various arbitrary values using cbor2.dumps() .我使用cbor2.dumps()尝试了各种任意值。 floats are always encoded as CBOR floats, and Decimal types are alwasy encoded as CBOR BigFloats. floats总是被编码为 CBOR 浮点数, Decimal类型总是被编码为 CBOR BigFloats。

>>> x=0.0 ; x ; d1 = dumps(x) ; d1 ; len(d1) ; dx = Decimal(x) ; d2 = dumps(dx) ; d2 ; len(d2)
0.0
b'\xfb\x00\x00\x00\x00\x00\x00\x00\x00'
9
b'\xc4\x82\x00\x00'
4

>>> x=1.0 ; x ; d1 = dumps(x) ; d1 ; len(d1) ; dx = Decimal(x) ; d2 = dumps(dx) ; d2 ; len(d2)
1.0
b'\xfb?\xf0\x00\x00\x00\x00\x00\x00'
9
b'\xc4\x82\x00\x01'
4

>>> x=1.5 ; x ; d1 = dumps(x) ; d1 ; len(d1) ; dx = Decimal(x) ; d2 = dumps(dx) ; d2 ; len(d2)
1.5
b'\xfb?\xf8\x00\x00\x00\x00\x00\x00'
9
b'\xc4\x82 \x0f'
4

>>> x=0.123456789 ; x ; d1 = dumps(x) ; d1 ; len(d1) ; dx = Decimal(x) ; d2 = dumps(dx) ; d2 ; len(d2)
0.123456789
b'\xfb?\xbf\x9a\xdd79c_'
9
b'\xc4\x8287\xc2W\x80\xe5\x18Js\xc0\xe4\x8f-\xf1\xc9\xf0\x90\xf4u%+\x93\xa7\n\x88\xa2?'
29

So I found the answer is a combination of using the canonical=True argument to dumps() and casting the floats to lower precision floats (using numpy ) where suitable (if any loss of precision is tolerable/acceptable).所以我发现答案是结合使用 dumps dumps()canonical=True参数并将浮点数转换为较低精度的浮点数(使用numpy )(如果任何精度损失是可以容忍/可接受的)。

NOTE: have to cast back to python float as cbor can't encode numpy classes at the momement.注意:必须转换回 python 浮点数,因为cbor目前无法编码numpy类。

>>> x=0.123456789 ; x ; d1=dumps(x, canonical=True) ; d1 ; len(d1)
0.123456789
b'\xfb?\xbf\x9a\xdd79c_'
9

>>> x=float( np.float32( 0.123456789 ) ) ; x ; d1=dumps(x, canonical=True) ; d1 ; len(d1)
0.12345679104328156
b'\xfa=\xfc\xd6\xea'
5

>>> x=float( np.float16( 0.123456789 ) ) ; x ; d1=dumps(x, canonical=True) ; d1 ; len(d1)
0.12347412109375
b'\xf9/\xe7'
3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM