Python Xlrd 浮点精度问题
我正在尝试使用xlrd模块将Excel(xlsx)文件中的数据导出到文本文件,但遇到了浮点数精度的问题。
我发现了一些类似的问题帖子,提到在最后16位小数中有精度丢失的情况。
下面是从xlsx文件中复制的数据:
VALUE;DATA
1.01 HELLO
2.11 1/1/2014
3.21 ONE
4.31 1/1/2014 12:14
5.441 $10
6.241 TWO
77.11 Zulfi
8.11 99
9.11 99.999
10.11 0
以下是我从xlrd得到的结果:
1.01|'HELLO'
2.1099999999999999|'2014-01-01 00:00:00.000000'
3.21|'ONE'
4.3099999999999996|'2014-01-01 12:14:00.000000'
5.4409999999999998|10.0
6.2409999999999997|'TWO'
77.109999999999999|'Zulfi'
8.1099999999999994|99.0
9.1099999999999994|99.998999999999995
10.109999999999999|0.0
- "2.11"变成了"2.1099999999999999","4.31"变成了"4.3099999999999996"等等……
- "$10"变成了"10"
- 日期值看起来有点不同(这个我理解,我知道我写的代码是怎样的)
我明白浮点数的一些奥秘,知道如果小数点后有太多数字,可能会导致精度丢失,但在这里我只有两位小数。
我正在通过与开源的ETL工具“Pentaho”(用Java编写)进行比较来测试输出,这个工具可以读写Excel文件,似乎没有问题,能够正确读取xlsx文件中的值(字段被读取为字符串和数字,长度为30,精度为20)。
这是Pentaho读取的内容:
VALUE;DATA
1.01;HELLO
2.11;2014/01/01 00:00:00.000
3.21;ONE
4.31;2014/01/01 12:14:00.000
5.441; 10.0
6.241;TWO
77.11;Zulfi
8.11; 99.0
9.11; 99.999
10.11; 0.0
下面是我的Python代码:
for rownum in xrange(sh.nrows):
for colnum in xrange(sh.ncols):
cell_obj = sh.cell(rownum,colnum)
cell_val=sh.cell_value(rownum,colnum)
if cell_obj.ctype == xlrd.XL_CELL_DATE:
year, month, day, hour, minute, second = xlrd.xldate_as_tuple(cell_val, wb.datemode)
py_date = datetime.datetime(year, month, day, hour, minute, second).strftime("%Y-%m-%d %H:%M:%S.%f")
cell_val = py_date
if (colnum==0):
row_values=repr(cell_val)
else :
row_values=row_values+fdel+repr(cell_val)
if (((row_values).find("\\n"))>-1):
NLFlag=1
file_output.write((row_values).replace('\\n','') + "\n")
row_values=''
file_output.close()
任何帮助都非常感谢。
谢谢
1 个回答
0
浮点数,也叫双精度实数,只有大约16位小数的精度。它们只能准确表示某些特定形式的小数,比如2的负n次方的分数,也就是像1/8或1/1024这样的数。其他的小数可能会不太准确。
如果你直接打印一个浮点数,系统会尽力把这个二进制的小数转换成十进制,所以你可能会看到2.099999999999这样的结果,而不是2.1。不过,如果你知道你的浮点数最多只需要保留3位小数,你可以在输出时强制它们四舍五入,比如使用字符串格式化函数
file_output.write('{0:.3f}'.format(f_num))
这样会正确地将f_num四舍五入,并补零到3位小数。
我猜xlrd库默认会把任何可以作为浮点数的字段都解释为浮点数。如果有一个选项可以强制所有读取的内容都作为字符串,那么你打印出来的内容就会和你读取的完全一致。