当前位置: 首页> 最新文章列表> 使用 json_decode 函数时,如何正确处理 JSON 中的数字精度问题?

使用 json_decode 函数时,如何正确处理 JSON 中的数字精度问题?

gitbox 2025-09-02

1. 为什么会发生数字精度问题?

JSON 格式使用的数字类型是基于 JavaScript 的 Number 类型,这种类型在精度上存在一定的限制。JavaScript 的 Number 类型是基于 IEEE 754 双精度浮点数标准(64位),可以表示的最大精度为 15 到 17 位有效数字。当 JSON 数据中包含超出此精度范围的数字时,在转换过程中就可能会丢失精度。

在 PHP 中,json_decode 默认将 JSON 中的数字解析为浮动类型(float),这也基于 IEEE 754 标准。这个类型与 JavaScript 的 Number 类型在精度上有一定差异,尤其是对于非常大的或非常小的数字。

例如,如果 JSON 数据包含 12345678901234567890 这样的数字,在使用 json_decode 解码时,可能会出现精度损失,导致得到的结果不准确。

2. 如何解决数字精度问题?

为了更好地控制数字的精度,PHP 提供了几种方法来处理 json_decode 中的数字精度问题。

2.1 使用 JSON_BIGINT_AS_STRING 选项

如果 JSON 中的数字可能会超出 float 精度范围(例如大整数),可以通过在调用 json_decode 时使用 JSON_BIGINT_AS_STRING 选项来将这些大数字解析为字符串,而不是浮动类型。这样可以避免精度损失,因为字符串不会丢失任何数字信息。

<span><span><span class="hljs-variable">$json</span></span><span> = </span><span><span class="hljs-string">'{"big_number": 12345678901234567890}'</span></span><span>;
</span><span><span class="hljs-variable">$data</span></span><span> = </span><span><span class="hljs-title function_ invoke__">json_decode</span></span><span>(</span><span><span class="hljs-variable">$json</span></span><span>, </span><span><span class="hljs-literal">false</span></span><span>, </span><span><span class="hljs-number">512</span></span><span>, JSON_BIGINT_AS_STRING);

</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$data</span></span><span>-&gt;big_number;  </span><span><span class="hljs-comment">// 输出 "12345678901234567890"</span></span><span>
</span></span>

通过这种方式,PHP 会把数字 12345678901234567890 保留为一个字符串,而不是将其转换为浮动数值,从而避免了数字精度的丢失。

2.2 手动处理数字精度

另一种解决方案是在接收到 JSON 数据之后,通过其他方式进行精度控制。例如,使用 GMP(GNU Multiple Precision)扩展处理大数字。GMP 扩展允许你处理任意精度的整数,可以在需要精确计算时使用。

<span><span><span class="hljs-variable">$json</span></span><span> = </span><span><span class="hljs-string">'{"big_number": 12345678901234567890}'</span></span><span>;
</span><span><span class="hljs-variable">$data</span></span><span> = </span><span><span class="hljs-title function_ invoke__">json_decode</span></span><span>(</span><span><span class="hljs-variable">$json</span></span><span>, </span><span><span class="hljs-literal">true</span></span><span>);

</span><span><span class="hljs-variable">$bigNumber</span></span><span> = </span><span><span class="hljs-title function_ invoke__">gmp_init</span></span><span>(</span><span><span class="hljs-variable">$data</span></span><span>[</span><span><span class="hljs-string">'big_number'</span></span><span>]);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-title function_ invoke__">gmp_strval</span></span><span>(</span><span><span class="hljs-variable">$bigNumber</span></span><span>);  </span><span><span class="hljs-comment">// 输出 "12345678901234567890"</span></span><span>
</span></span>

在这个例子中,我们将数字解析为字符串,并使用 GMP 来确保数字精度不受损失。

2.3 使用合适的数据格式

如果 JSON 数据本身就包含了数字和字符串混合的情况,最好在处理 JSON 时明确区分数据类型。对于包含非常大或者非常小数字的场景,最好在生成 JSON 数据时确保使用合适的数据格式。可以考虑使用科学计数法或字符串形式传递大数字,以减少精度丢失的风险。

<span><span><span class="hljs-variable">$json</span></span><span> = </span><span><span class="hljs-string">'{"big_number": "12345678901234567890"}'</span></span><span>;
</span><span><span class="hljs-variable">$data</span></span><span> = </span><span><span class="hljs-title function_ invoke__">json_decode</span></span><span>(</span><span><span class="hljs-variable">$json</span></span><span>, </span><span><span class="hljs-literal">true</span></span><span>);

</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-variable">$data</span></span><span>[</span><span><span class="hljs-string">'big_number'</span></span><span>];  </span><span><span class="hljs-comment">// 输出 "12345678901234567890"</span></span><span>
</span></span>

通过这种方式,避免了 PHP 将数字解析为浮动类型的问题,保持了数据的完整性。

3. 其他注意事项

3.1 浮动类型的比较问题

在 PHP 中,由于浮动类型的数字可能会丢失精度,进行浮动类型的比较时可能会出现不准确的情况。为了避免这种问题,可以使用字符串或精确数字类型来进行比较,尤其是在涉及金融或其他需要高精度的计算时。

3.2 性能考量

使用 JSON_BIGINT_AS_STRING 选项会导致 PHP 在解析 JSON 时将所有大整数处理为字符串,这可能会影响性能,尤其是在需要处理大量数据时。因此,在选择解决方案时,需要权衡数据精度与性能之间的平衡。

4. 总结

处理 JSON 数据时,数字精度问题是一个不可忽视的挑战,特别是当涉及到大数字或高精度需求时。PHP 提供了多种方法来解决这一问题,例如使用 JSON_BIGINT_AS_STRING 选项将大数字解析为字符串,或者使用 GMP 扩展进行精确计算。根据实际需求选择合适的处理方式,能够确保数据的准确性和系统的稳定性。