为什么要使用 JSON 中的字符串来表示十进制数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35709595/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 18:18:04  来源:igfitidea点击:

Why would you use a string in JSON to represent a decimal number

jsonserializationpaypal

提问by kag0

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

一些 API,如贝宝 API,使用 JSON 中的字符串类型来表示十进制数。所以"7.47"代替7.47.

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 数值类型会是一个好主意?AFAIK 数值类型允许无限精度以及科学记数法。

回答by dthorpe

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

将 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 规范确实没有为数值指定精度。这并不意味着 JSON 数字具有无限精度。这意味着未指定数字精度,这意味着 JSON 实现可以自由选择对其实现或目标方便的任何数字精度。如果您的应用程序有特定的精度要求,这种可变性可能会很痛苦。

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:

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

  1. Irrational numbers (like pi and e)

  2. 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. 无理数(如 pi 和 e)

  2. 1.7 以 10 进制表示法具有有限表示,但在二进制(以 2 为基数)表示法中,1.7 无法准确编码。即使有近乎无限数量的二进制数字,您也只会接近 1.7,但永远不会准确地达到 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.

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

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.

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

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.

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

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 生产者(例如 JRuby)中,BigInteger 值会自动作为字符串输出到 JSON,主要是因为 BigInteger 的范围和精度比 IEEE 双精度浮点数大得多。将 BigInteger 值减少为 double 以输出为 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 规范 ( http://www.json.org/) 明确指出 NaN 和无穷大 (INF) 对于 JSON 数值无效。如果需要表达这些边缘元素,则不能使用 JSON 编号。您必须使用字符串或对象结构。

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.

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

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

回答by Ole

Summarized Version

总结版

Just quoting from @dthorpe's answer, as I think this is the most important point:

仅引用@dthorpe 的回答,因为我认为这是最重要的一点:

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 规范 ( http://www.json.org/) 明确指出 NaN 和无穷大 (INF) 对于 JSON 数值无效。如果需要表达这些边缘元素,则不能使用 JSON 编号。您必须使用字符串或对象结构。