1. ホーム
  2. json

[解決済み] なぜJSONで10進数を表す文字列を使用するのか?

2023-01-30 22:04:54

質問

いくつかのAPI、例えば ペイパルAPI のように、一部のAPIではJSONの文字列型を使って10進数を表現しています。そのため "7.47" の代わりに 7.47 .

なぜ/いつ、これはjsonの数値型を使用するよりも良いアイデアなのでしょうか?AFAIKは、数値の値型は、科学的記法と同様に無限の精度を可能にします。

どのように解決するのですか?

JSONで数値を文字列として転送する主な理由は、転送時の精度の低下やあいまいさをなくすためです。

JSON仕様が数値の精度を規定していないことは事実です。これは、JSONの数値が無限の精度を持つという意味ではありません。数値の精度が指定されていないため、JSON の実装では、その実装や目標に便利な数値の精度を自由に選択できることを意味します。 アプリケーションに特定の精度の要件がある場合、この多様性が問題となることがあります。

精度の損失は一般に、数値のJSONエンコーディングでは明らかになりませんが(1.7は簡潔でよい)、受信側のJSON解析と中間表現で明らかになります。 JSONのパース機能は、1.7をIEEEの倍精度浮動小数点数に極めて合理的にパースします。しかし、有限長/有限精度の 10 進表現は、10 進展開が有限の桁のシーケンスとして表現できない数字に常に遭遇することになります。

  1. 不合理数 (円周率や電子のような)

  2. 1.7 は、基数 10 の表記法では有限の表現を持ちますが、2 進法 (base 2) では 1.7 を正確に符号化することはできません。2 進法の桁数が無限に近い場合でも、1.7 に近づくだけで、正確に 1.7 に到達することはありません。

したがって、1.7 をメモリ内の浮動小数点数に解析し、その数をプリントアウトすると、1.7 ではなく 1.69 のようなものが返される可能性が高いです。

JSON 1.7 の値の消費者は、固定小数点データ型または任意の精度の "string int" データ型を使用するなど、値を解析してメモリ内に保持するためにより高度な技術を使用できますが、これは一部の数値の変換で精度が失われる可能性を完全に排除するものではありません。 そして現実には、ほとんどの状況で利点が少なく、メモリと CPU のコストが高いため、このような極端な手段をわざわざ取る JSON パーサーは非常に少ないのです。

したがって、正確な数値を消費者に送信したい場合、その値を典型的な内部数値表現に自動的に変換したくないのであれば、最善の策は、数値を文字列として送信し、数値演算が必要な場合にその文字列がどのように処理されるべきかを消費者に正確に伝えることです。

たとえば、以下のようになります。これは、BigInteger の範囲と精度が IEEE 倍精度浮動小数点よりもはるかに大きいことが主な理由です。JSONの数値として出力するためにBigInteger値をdoubleに縮小すると、多くの場合、重要な桁が失われます。

また、JSONの仕様( http://www.json.org/ )では、JSONの数値に対してNaNや無限大(INF)は無効であると明示されています。 これらのフリンジ要素を表現する必要がある場合、JSONの数値は使えません。文字列かオブジェクト構造体を使う必要があります。

最後に、数値データを文字列として送信することを選択する原因となるもう一つの側面があります。それは、表示形式の制御です。 先頭のゼロと末尾のゼロは、数値にとっては重要ではありません。JSONの数値値2.10または004を送信する場合、内部数値形式への変換後は、2.1および4として表示されます。

ユーザーに直接表示されるデータを送信する場合、おそらくお金の数字が画面上できれいに並び、小数点以下が揃うようにしたいことでしょう。そのための 1 つの方法は、表示用にデータをフォーマットする責任をクライアントに負わせることです。 もう一つの方法は、サーバーに表示用のデータをフォーマットさせることです。クライアントにとっては、画面に表示する方が簡単かもしれませんが、クライアントがその値に対して計算を行う必要がある場合、文字列から数値を取り出すのが難しくなる可能性があります。