Non-Finite Numbers
Unlike JSON [RFC 8259], CBOR supports the non-finite floating-point constructs defined byIEEE
754
, known as
NaN
(not a number) and Infinity
.
This implementation provides multiple levels of support, intended to
accommodate different needs.
This is accomplished without specific decoder or encoder options;
it is entirely based on API method selections.
The following table outlines the supported alternatives:
Designation | Comment |
---|---|
BASIC | Only "regular" floating-point numbers are accepted. |
EXTENDED | All floating-point numbers except for non-trivial NaNs are accepted.
In the list below,
NaN refers to "simple" NaNs
(in deterministically encoded CBOR represented by f97e00 ),
while Infinity refers to
positive infinity (f97c00 ) and negative infinity (f9fc00 ).
The Java counterparts are represented by Double.NaN ,
Double.POSITIVE_INFINITY ,
and Double.NEGATIVE_INFINITY respectively. |
COMPLETE | All floating-point numbers are accepted. |
CBORException
to be thrown.
Note that the constraints apply to encoding as well.
Encoding Methods
BASIC | |
new CBORFloat(double) | // "Regular" number |
EXTENDED | |
CBORFloat.createExtendedFloat(double) | // "Regular" number, NaN, or Infinity |
COMPLETE | |
// Select suitable method: | |
new CBORFloat(double) | // "Regular" number |
new CBORNonFinite(long) | // Arbitrary non-finite number |
CBORNonFinite.createPayloadObject(long) | // Application-specific data |
Decoding Methods
BASIC | |
cborObject.getFloat64() | // "Regular" number |
EXTENDED | |
cborObject.getExtendedFloat64() | // "Regular" number, NaN, or Infinity |
COMPLETE | |
// Check what the decoder returned: | |
if (cborObject instanceof CBORNonFinite nf) { | |
// Non-finite number to process | |
// Select suitable method: | |
nf.getNonFinite64() | // Arbitrary non-finite number |
nf.getPayload() | // Application-specific data |
} else { | |
// "Regular" number to process | |
cborObject.getFloat64() | // "Regular" number |
} |
Payload Option
Traditionally, the non-finite number space is used for propagating
math-related problems such as division by zero.
However, in some cases there may be a desire providing more application specific data,
like information related to a faulty sensor that needs attention.
The
CBORNonFinite.createPayloadObject(long)
and CBORNonFinite.getPayload()
methods were designed for this particular purpose.
To obviate the need defining another CBOR type, these methods
are "piggybacking" on the existing non-finite number space.
The following table represents these methods from a developer perspective:
Payload |
---|
d51-d0 in big-endian order |
The payload bits are conceptually put into an
IEEE
754
64
-bit object having the following layout:
Sign | Exponent | Significand |
---|---|---|
0 | 11111111111 | d0-d51 in little-endian order |
For setting the sign bit, see
CBORNonFinite.setSign(boolean)
.
The reason for reversing the payload bits is to ensure that a specific bit will remain
in a fix position (maintain the same value), independent of the size of the
IEEE
754
variant used for encoding.
Note that the encoder will (due to CBOR deterministic encoding rules), select
the shortest serialization required to properly represent the payload.
The following table shows a few examples:
Payload (hex) | CBOR Encoding | Diagnostic Notation |
---|---|---|
0 | f97c00 | Infinity |
1 | f97e00 | NaN |
2 | f97d00 | float'7d00' |
3ff | f97fff | float'7fff' |
400 | fa7f801000 | float'7f801000' |
7fffff | fa7fffffff | float'7fffffff' |
800000 | fb7ff0000010000000 | float'7ff0000010000000' |
fffffffffffff | fb7fffffffffffffff | float'7fffffffffffffff' |
0
and having the sign bit set, would encode as f9fc00
(-Infinity
).