Python fastavro错误地转换浮点数

4

我在使用fastavro(和普通的avro)将在我的avro模式中定义为float的数字进行转换时遇到了一些问题,我无法理解这个问题。我确定它与数据类型存储有关,但我并不理解。简而言之,当值超过约9个数字时,我将记录传递到fastavro.dump中,然后将结果传递回fastavro.load,此时转换不会返回相同的结果。

import fastavro
from io import BytesIO

schema = {
  'name': 'Person',
  'type': 'record',
  'fields': [
    {'name': 'EmpName', 'type': 'string'},
    {'name': 'ID', 'type': 'float'}]}

origRecord = {'EmpName': 'BillyBob', 'ID': 1111000000}

buf = BytesIO()
fastavro.dump(buf, origRecord, schema)
avroMsg = buf.getvalue()

buf = BytesIO(avroMsg)
afterConversion = fastavro.load(buf, schema)
print(origRecord['ID'])
print(afterConversion['ID'])

输出结果如下所示:
1111000000
1111000064.0

我希望转换后的结果会出现 .0,但实际值的变化让我感到困惑。随着输入值的变化,两者之间的差异也从 -63 变化到 +64(这可能指出了实际发生的情况)。在模式中将类型更改为 double/long/int 似乎可以解决这个问题,就我的测试而言是如此。当使用 float 类型时,较小的值不会表现出这种行为。


这是float(单精度)数据类型的一个众所周知的限制。请注意,数据类型是特定于avro而不是Python的。 - John Y
我不确定我同意这是众所周知的,我在发帖之前进行了大量搜索,但没有找到类似问题的证据。我想这一切都取决于寻找正确的事物。 - supahcraig
当我使用Python浮点数时,遇到了同样的问题,我只是在模式中将类型从float更改为double。现在Avro文件中的值具有正确的精度。 - Ben Dalling
1个回答

2

请查看avro规范https://avro.apache.org/docs/1.8.1/spec.html

浮点数用4个字节写入。浮点数将转换为32位整数,使用与Java的floatToIntBits方法相同的方法,并以小端格式编码。

因此,精度损失是可预测的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接