我试图读取和xlsx文件,以批量导入到mysql数据库。
我可以成功地读取文本字段,但是当涉及到大小数点的数字时,它给出了错误的结果。
我正在使用github的nuovo /电子表格处理程序
SpreadsheetReader.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.9999999
16983999.9999999
-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
有人知道为什么会这样吗?
发布于 2015-12-28 12:23:45
您无意中遇到的问题与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项的和。
计算机试图通过找到一个表示形式来解决这个问题,这种表示法在大多数情况下甚至非常接近实数。这些表示的好坏很大程度上取决于用来存储浮点数的位数。您投入的内存越多,表示的效果就越好。
在您的情况下,excel只需使用更多的内存来存储数字的分数部分,而不是php解释器。当您将这些数字从excel导入到php时,这会导致某种偏差。
编辑:
这个问题的一个简单例子是将分数1/3表示为十进制数。你可能知道,没有精确的表示法,很多人只会写0.3333333.并按他们的需要增加3倍。如果我们想把这个数字写在一个基于数字3的数字系统中,事情会变得非常容易,因为我们只需要写3^-1。
编辑2:也许您可以尝试将这些大数字作为字符串导入,这些字符串可以在php中具有任意长度。如果您只是使用php导入数据并希望存储这些数据,这可能会有所帮助,例如,wihtin数据库可能具有完全不同的精度。
编辑3:数字的精度是通过php配置的,可以设置,参见http://php.net/manual/en/ini.core.php#ini.precision。
编辑4:如果您想深入研究浮点精度这一主题,那么这是一篇非常好的文章:goldberg.html
https://stackoverflow.com/questions/33864553
复制相似问题