为什么要使用 JSON 中的字符串来表示十进制数 [英] Why would you use a string in JSON to represent a decimal number

查看:17
本文介绍了为什么要使用 JSON 中的字符串来表示十进制数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

某些 API,例如 paypal API 使用JSON 中的字符串类型来表示十进制数.所以 "7.47" 而不是 7.47.

Some APIs, like the paypal API use a string type in JSON to represent a decimal number. So "7.47" instead of 7.47.

为什么/什么时候这比使用 json 数值类型更好?AFAIK 数值类型允许无限精度以及科学记数法.

Why/when would this be a good idea over using the json number value type? AFAIK the number value type allows for infinite precision as well as scientific notation.

推荐答案

将 JSON 中的数值作为字符串传输的主要原因是为了消除传输中的任何精度损失或歧义.

The main reason to transfer numeric values in JSON as strings is to eliminate any loss of precision or ambiguity in transfer.

JSON 规范确实没有为数值指定精度.这并不意味着 JSON 数字具有无限精度.这意味着未指定数字精度,这意味着 JSON 实现可以自由选择对其实现或目标方便的任何数字精度.如果您的应用程序有特定的精度要求,这种可变性可能会很麻烦.

It's true that the JSON spec does not specify a precision for numeric values. This does not mean that JSON numbers have infinite precision. It means that numeric precision is not specified, which means JSON implementations are free to choose whatever numeric precision is convenient to their implementation or goals. It is this variability that can be a pain if your application has specific precision requirements.

精度损失通常在数值的 JSON 编码中并不明显(1.7 很好且简洁),但在接收端的 JSON 解析和中间表示中表现出来.JSON 解析函数可以相当合理地将 1.7 解析为 IEEE 双精度浮点数.然而,有限长度/有限精度的十进制表示总是会遇到其十进制扩展不能表示为有限数字序列的数字:

Loss of precision generally isn't apparent in the JSON encoding of the numeric value (1.7 is nice and succinct) but manifests in the JSON parsing and intermediate representations on the receiving end. A JSON parsing function would quite reasonably parse 1.7 into an IEEE double precision floating point number. However, finite length / finite precision decimal representations will always run into numbers whose decimal expansions cannot be represented as a finite sequence of digits:

  1. 无理数(如 pi 和 e)

  1. Irrational numbers (like pi and e)

1.7 以 10 进制表示法具有有限表示,但在二进制(以 2 为基数)表示法中,1.7 无法准确编码.即使有近乎无限数量的二进制数字,您也只会接近 1.7,但永远不会精确到 1.7.

1.7 has a finite representation in base 10 notation, but in binary (base 2) notation, 1.7 cannot be encoded exactly. Even with a near infinite number of binary digits, you'll only get closer to 1.7, but you'll never get to 1.7 exactly.

因此,将 1.7 解析为内存中的浮点数,然后打印出该数字可能会返回类似 1.69 而不是 1.7 的内容.

So, parsing 1.7 into an in-memory floating point number, then printing out the number will likely return something like 1.69 - not 1.7.

JSON 1.7 值的消费者可以使用更复杂的技术来解析和保留内存中的值,例如使用定点数据类型或具有任意精度的string int"数据类型,但这不会完全消除某些数字的转换精度损失的幽灵.现实情况是,很少有 JSON 解析器会为这种极端的措施而烦恼,因为在大多数情况下收益很低,而且内存和 CPU 成本很高.

Consumers of the JSON 1.7 value could use more sophisticated techniques to parse and retain the value in memory, such as using a fixed-point data type or a "string int" data type with arbitrary precision, but this will not entirely eliminate the specter of loss of precision in conversion for some numbers. And the reality is, very few JSON parsers bother with such extreme measures, as the benefits for most situations are low and the memory and CPU costs are high.

因此,如果您想向消费者发送精确的数值,并且不想将该值自动转换为典型的内部数字表示,那么最好的办法是将数值作为字符串发送出去并告诉如果需要对其执行数字操作,消费者应该如何处理该字符串.

So if you are wanting to send a precise numeric value to a consumer and you don't want automatic conversion of the value into the typical internal numeric representation, your best bet is to ship the numeric value out as a string and tell the consumer exactly how that string should be processed if and when numeric operations need to be performed on it.

例如:在一些 JSON 生成器(例如 JRuby)中,BigInteger 值会自动作为字符串输出到 JSON,主要是因为 BigInteger 的范围和精度比 IEEE 双精度浮点数大得多.将 BigInteger 值减少为 double 以输出为 JSON 数字通常会丢失有效数字.

For example: In some JSON producers (JRuby, for one), BigInteger values automatically output to JSON as strings, largely because the range and precision of BigInteger is so much larger than the IEEE double precision float. Reducing the BigInteger value to double in order to output as a JSON numeric will often lose significant digits.

此外,JSON 规范 (http://www.json.org/) 明确指出 NaN和 Infinities (INF) 对于 JSON 数值无效.如果需要表达这些边缘元素,则不能使用 JSON 编号.您必须使用字符串或对象结构.

Also, the JSON spec (http://www.json.org/) explicitly states that NaNs and Infinities (INFs) are invalid for JSON numeric values. If you need to express these fringe elements, you cannot use JSON number. You have to use a string or object structure.

最后,还有另一个方面可以导致选择将数字数据作为字符串发送:显示格式的控制.前导零和尾随零对数值无关紧要.如果您发送 JSON 数字值 2.10 或 004,在转换为内部数字形式后,它们将显示为 2.1 和 4.

Finally, there is another aspect which can lead to choosing to send numeric data as strings: control of display formatting. Leading zeros and trailing zeros are insignificant to the numeric value. If you send JSON number value 2.10 or 004, after conversion to internal numeric form they will be displayed as 2.1 and 4.

如果您发送的数据将直接显示给用户,您可能希望您的货币数字在屏幕上排列整齐,十进制对齐.一种方法是让客户端负责格式化要显示的数据.另一种方法是让服务器格式化数据以进行显示.客户端在屏幕上显示内容可能更简单,但是如果客户端还需要对值进行计算,这会使从字符串中提取数值变得困难.

If you are sending data that will be directly displayed to the user, you probably want your money figures to line up nicely on the screen, decimal aligned. One way to do that is to make the client responsible for formatting the data for display. Another way to do it is to have the server format the data for display. Simpler for the client to display stuff on screen perhaps, but this can make extracting the numeric value from the string difficult if the client also needs to make computations on the values.

这篇关于为什么要使用 JSON 中的字符串来表示十进制数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆