我正在使用PHP创建一个Web服务。 我使用POST / GET方法以JSON格式传递一些数据。 我传递的数据如下:
WEBSERVICE_URL?data={
"action":"facebook_contacts",
"contacts":[
{
"uid" : 100007356270051,
"pic" : "https:\/\/fbcdn-profile-a.akamaihd.net\/hprofile-ak-prn2\/t5\/1118559_592238484_1133654491_s.jpg",
"name" : "Smit Nebhwani"
},
{
"uid" : 1289351411,
"pic" : "https:\/\/fbcdn-profile-a.akamaihd.net\/hprofile-ak-prn2\/t5\/1118043_1289351411_469744700_s.jpg",
"name" : "Swetang Thakkar"
},
{
"uid" : 1506453812,
"pic" : "https:\/\/fbcdn-profile-a.akamaihd.net\/hprofile-ak-ash2\/t5\/1118635_1506453812_1534707268_s.jpg",
"name" : "Ravi M Maru"
},
{
"uid" : 100004690921571,
"pic" : "https:\/\/fbcdn-profile-a.akamaihd.net\/static-ak\/rsrc.php\/v1\/yh\/r\/C5yt7Cqf3zU.jpg",
"name" : "Qa Orig"
},
{
"uid" : 100007093534387,
"pic" : "https:\/\/fbcdn-profile-a.akamaihd.net\/static-ak\/rsrc.php\/v1\/yh\/r\/C5yt7Cqf3zU.jpg",
"name" : "Ru Kan"
},
{
"uid" : 100007356270051,
"pic" : "https:\/\/fbcdn-profile-a.akamaihd.net\/hprofile-ak-ash2\/t5\/1076776_100007356270051_49934227_s.jpg",
"name" : "Jonson Bool"
}
]
}
并且在我的Web服务中,迭代到contact
数组并将其转换为关联数组并尝试为每个数组回显uid
参数的值。它回应如下:
1.0000352215999E+14
1289351411
1506453812
1.0000469092157E+14
1.0000709353439E+14
1.0000735627005E+14
为什么数字会像这样转换?
请指导我解决这个问题。 谢谢你提前
答案 0 :(得分:1)
在PHP脚本之上添加此ini_set('precision', 20);
。
<?php
echo 100007356270051; //"prints" your erroneous value.. like 1.0000735627005E+14
echo "\n";
ini_set('precision', 20); // Set the precision here
echo 100007356270051; //"prints" 100007356270051
答案 1 :(得分:0)
在循环和显示之前,您需要将大整数转换为字符串。
json_decode($json, true, 512, JSON_BIGINT_AS_STRING)
答案 2 :(得分:0)
您需要将大整数解码为字符串,以避免在PHP中将它们转换为浮点数:
$data = json_decode($json, true, 512, JSON_BIGINT_AS_STRING);
此选项仅在PHP 5.4之后可用。对于较低版本,您必须寻找支持相同功能的自定义JSON解码器。
答案 3 :(得分:0)
在您的示例中,您的数字未被转换:您看到的数字的表示不同,因为它们代表的某些内容太大而不是整数。需要以“无限精度”存储的大数字最好存储为字符串 - 特别是如果它们是标识符(如您的情况)。我希望你不打算将它们视为一个数字(用它们做数学:加,乘等) - 所以不要将它们存储为数字。
在几个答案中已经指出,有一种方法可以在json
中使用JSON_BIGINT_AS_STRING
标记强制执行json_decode
函数中的此行为。
然而 - 比您使用 “转换”的数字略大 - 也就是说,它们会转换为double
,并且在此过程中会失去精确度。丢失精度意味着并非所有超过特定大小的整数值都可以表示 - 并且它们将“舍入”到附近的值(可以用双精度表示)。
为了表明我对“精度损失”的意思,这里有一个小测试程序:
<?php
$a=100007356270051000;
ini_set('precision', 22);
for($m = 0; $m < 3; $m++) {
echo "m = $m\n";
for($n = 0; $n < 5; $n++) {
echo $a + $n."\n";
}
$a = $a * 10;
echo "\n";
}
?>
其中给出了以下输出:
m = 0
100007356270051000
100007356270051001
100007356270051002
100007356270051003
100007356270051004
m = 1
1000073562700510000
1000073562700510001
1000073562700510002
1000073562700510003
1000073562700510004
m = 2
10000735627005100032
10000735627005100032
10000735627005100032
10000735627005100032
10000735627005100032
如您所见,数字略大于您的数字(只有五位数)无法再表示而不会失去准确性 - 当您添加1时,结果不会改变。这是因为内部数字已转换为double
,因为它太大而无法放入int
。这将无声地发生,将将来导致您的问题。
注意大整数 - 它不像你想要的那样精确。