php-excel阅读器错误读取数字


php excel reader reading numbers incorrectly

我正在尝试读取和xlsx文件以批量导入到mysql数据库。

我可以成功地读取文本字段,但当涉及到大小数点的数字时,它会给出错误的结果。

我正在使用github 的nuovo/spreadsheet阅读器

电子表格阅读器.php电子表格阅读器_XLSX.php

index.php

$Reader = new SpreadsheetReader($orgFilename);
$count = count($Reader);
foreach ($Reader as $Row)
{
    echo $Row[0] . '<br>';
}

这是我的excel数据

690835388.737296
-553772409.572704
16983999.99999999
16983999.99999999
-904762663.342704
0.439514518724299
89055169.9716966
171930071.634401
35291999.9999995
1151681063.10099

输出为

690835388.7373
-553772409.5727
16984000
16984000
-904762663.3427
0.4395145187243
89055169.971697
171930071.6344
35291999.999999
1151681063.101

有人知道为什么会发生这种事吗?

您偶然遇到的问题与SpreadsheetReader无关。它完全基于excel和php中浮点数字的不同精度。

当我从你的例子中取一个数字,简单地做:

echo 1151681063.10099;

那么输出将是1151681063.101

每个软件都使用一定数量的内存来表示数字。其中一些内存用于表示数字的整数部分,一些量用于表示小数部分。

对于整数来说,这很容易。每一个十进制整数都可以表示为一个二进制数,这就是计算机所做的。他们用2的倍数和来做算术。

例如,数字14可以表示为2^3+2^2+2^1=8+4+2=14。只要你有足够的内存来存储,这对每个整数都有效

对于小数来说,情况就完全不同了。我们人类以10的分数为基础进行浮点计算。例如,0.25=0.2+0.05=10^-1*2+10^-2*5。所以浮点数是通过将1/10、1/100、1/1000…的倍数相加来设置的

另一方面,计算机必须将这些数字表示为1/2、1/4、1/8、1/16…的总和

对于上面的0.25的例子,这很容易,因为我们可以说它相当于1/4,它有一个干净的二进制数表示(2^-2)。

不幸的是,对于其他数字来说,情况并不那么顺利。如果我们试图把0.3转换成二进制数,就会遇到麻烦。这个数字没有精确的二进制表示,因为我们不能把它写成不同2^-N项的和。

计算机试图通过找到一个在大多数情况下甚至非常接近实数的表示来解决这个问题。这些表示的好坏在很大程度上取决于用于存储浮点数的位数。你投入的内存越多,表现就越好。

在您的例子中,与php解释器相比,excel只是使用更多的内存来存储数字的小数部分。当您将这些数字从excel导入php时,这会导致某种偏差。

编辑:

这个问题的一个简单例子是将分数1/3表示为十进制数。正如你可能知道的,没有精确的表示,很多人只会写0.3333333……并根据需要添加3。如果我们想把这个数字写在一个基于数字3的数字系统中,事情会变得非常容易,因为我们只需要写3^-1。

编辑2:也许您可以尝试将这些大数字导入为字符串,这些字符串在php中可以具有任意长度。如果您只是使用php导入数据,并希望将这些数据存储在一个精度可能完全不同的数据库中,这可能会有所帮助。

编辑3:数字的精度是通过php.ini配置的,可以进行设置,请参阅http://php.net/manual/en/ini.core.php#ini.precision

编辑4:如果你想更深入地研究浮点精度的话题,那么这是一篇非常好的文章:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html