That's an entertaining response from Joe, but it's not a response to anythingWe clearly specify how long, double, int, BigInteger, String -> BigDecimal conversion in javadoc. The semantics of BigDecimal are used for all other purposes. What else do you want me to specify in javadoc ? I can do that if there is better way to document it.
that has been suggested by either Martin or myself in the conversation so
far. We all came into this understanding that floating point numbers are
increasingly widely spaced as their magnitude increases.
To put a finer point on it:
1. Every Java byte, short, char, int, and float value has an exact double
2. The larger magnitude long values do not have an exact double representation
3. There are an effectively infinite number of BigInteger and BigDecimal
values that have no double representation
4. Every BigDecimal value can be exactly represented by a String, although in
some cases it might take more memory to do so
I take it as a given that everybody involved in this conversation understood
all of the above before we got started, but I guess it helps to articulate
the points for the sake of clarity.
Getting back to the discussion about JsonNumber, here's the context I was
1. The JSON data format is most commonly used to interchange data with web
browsers, where the overwhelmingly common programming environment is
rounded to a nearby double-precision floating point value. I don't think we
can even assume a particular rounding rule (down, up, nearest, other?!).
3. The designer of an application that produces or consumes JSON data must
assume that all numbers in the data structure might be shoe-horned into
doubles, with the attending loss of precision, *unless* they know for certain
that the data structure will never be processed in a web browser. (And how
limiting of an assumption is that, over the lifetime of a system first
designed in 2013?)
In practice, because of the above concerns and the ubiquity of web browsers,
exact numeric values exchanged in JSON data structures (for example, unique
IDs and monetary amounts) are usually transmitted as quoted strings rather
than as numbers.
But even given the inherent dangers and limitations of trusting that a number
you put into a JsonNumber will retain its precision at every stage of
processing, nobody was suggesting that we just throw up our hands and let
JSR353's JsonNumber play fast and loose with numeric precision. We're merely
asking that common expectations and common-case performance constraints be
My suggestion was simply that we should be careful in the specification of
JsonNumber on these points:
1. JsonNumber should explicitly specify that it preserves the full precision
of the value it was constructed from (this is potentially relevant for any
JsonNumber constructed from a
long, BigInteger, BigDecimal, or String value, but especially delicate on data paths like
String -> JsonNumber -> BigDecimal or BigDecimal -> JsonNumber -> String
where trailing zeroes are significant)
2. JsonNumber should be specified so that the implementation has the optionShould you want this to be limited to equality/hashCode or want to use for toString represenation ? Say JsonNumber num1 is constructed with double 10.0d, JsonNumber num2 is constructed with integer 10, do you want num1 and num2 to be equal ? What about representation, are you ok with both being written on the wire as 10 ? If that's the case,
to store the value as a String internally. This makes it cheap in both time
and space to pass values through verbatim from one system to another. The
overwhelming majority of JsonNumber instances will either begin their life as
a String (parsed from an input stream) or end their lives as a String
(serialized to an output stream). Additionally, there are plenty of use cases
where the number will be read from an input stream, shuffled around (say, as
a member of a JsonObject or JsonArray) and then written back out without ever
being asked its numeric value.
3. JsonNumber's equals() and hashCode() methods should be specified in a
manner compatible with an internal String representation (the tricky part
here, as raised by Jitu in the original thread, is that we'd need to account
for the rare case that a number uses exponential notation) so a JsonNumber
implementation can correctly compare itself to another JsonNumber without
creating additional objects
a. the promise in point 1 to *retain* precision and scale in JsonNumber;
b. the common-case performance concerns in points 2 and 3 about tying
JsonNumber to BigDecimal,
I submit that it goes against all reasonable expectations that a JsonNumber received on the wire as
"10" would not compare equal to a JsonNumber received on the wire as "10.0" or
"10.00". Leading and trailing zeroes that don't contribute to the number's magnitude should be
disregarded for the purposes of equality. I think specifying otherwise in a
So now that we're all (hopefully!) discussing the same topic, I'm keen to
hear your insights.
On 2013-01-24, at 12:07 AM, Jitendra Kotamraju wrote:
Martin proposed different algorithm for JsonNumber equals()/hashCode() in his
review . I am including Joe's response on this.
I am also ccing him, please include him in replies as he is not on the users
mailing list. His response is as follows:
In general, it is essentially unpredictable from inspection which decimal
strings are exactly representable as double floating-point value. Yes, there
are many cases which are easy, but quick, pick which one of these two values
is exactly representable as double:
Need more time? Did you correctly pick the first one?
Using BigDecimal as the numerical back store removes the concern for this and many other
numerical anomalies at the cost of the "10.0" is not always equivalent to
"10" issue. However, the latter problem is manageable whereas predicting string to
double conversion is much less so.
The equals / hashCode contracts of BigDecimal and long-standing and should by
built-upon by the JSON API. You can define an alternative equals / hashCode
definition (the hashcode in the pdf isn't quite right, the a numeric zero
needs to be handled separately), but that introduces other kinds of anomalies.
[json-processing-spec users] Re: BigDecimal for equals()/hashCode()