Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Special floating point values have no encoding #2

Open
willglynn opened this Issue · 7 comments

6 participants

@willglynn

The "floating point numbers" section refers to 64-bit double precision -- presumably IEEE-754 -- and specifies how to encode typical numbers, but it does not specify encoding of special values such as NaN or infinities. This is undesirable, as now any object graph that includes any IEEE-754 floating point field could conceivably become unserializable, depending on the value that field contains.

JSON makes no allowances for NaN or +/-Inf, forcing tools to use tricks like serializing these values as strings, and coercing certain strings ("NaN") back into their floating-point counterparts on deserialization. Not only does this add semantics on an ad-hoc basis outside the JSON specification, it is simply too much magic for my taste. On the other hand, YAML provides .inf, -.Inf, and .NAN as language-independent tokens representing these particular floating point values. I find this much preferable, as it causes no ambiguity.

I'd like the encoding of these values to be specified, since edn seems to be aiming at general-purpose data interchange, and the set of floating point numbers includes these special values.

@seh
seh commented

Looking around for precedent, neither Common Lisp nor Emacs Lisp have such literals, as neither accommodate the concept of infinite numbers. To get there, there are some implementation-specific extensions, requiring configuration of over- and underflow traps to put these to use:

  • CMUCL defines extensions:(short|single|double|long)-float-(posi|nega)tive-infinity.
  • SBCL defines sbt-ext:(short|single|double|long)-float-(posi|nega)tive-infinity.
  • The IEEE Floats library defines :not-a-number, :positive-infinity, and :negative-infinity.
@cambecc

For more precedent, clojure itself formats these special values as NaN, Infinity, and -Infinity:

user=> (/ 0.0 0.0)
NaN
user=> (/ 1.0 0.0)
Infinity
user=> (/ -1.0 0.0)
-Infinity

These same formats have precedent in the JVM, both on output:

System.out.println(Double.NaN);
System.out.println(Double.POSITIVE_INFINITY);
System.out.println(Double.NEGATIVE_INFINITY);

NaN
Infinity
-Infinity

...and input:

System.out.println(Double.valueOf("NaN"));
System.out.println(Double.valueOf("+NaN"));
System.out.println(Double.valueOf("-NaN"));
System.out.println(Double.valueOf("Infinity"));
System.out.println(Double.valueOf("+Infinity"));
System.out.println(Double.valueOf("-Infinity"));

NaN
NaN
NaN
Infinity
Infinity
-Infinity

edn should plug the hole left open by JSON and specify these special values as valid floating point numbers. The following grammar change would be sufficient:

floating-point-number
  int M
  int frac
  int exp
  int frac exp
  NaN
  +NaN
  -NaN
  Infinity
  +Infinity
  -Infinity

EDIT:

Actually, it is not so simple. The above grammar would make it impossible to distinguish between these special floating point numbers and symbols. One possible solution is to define a built-in tag:

#float NaN
#float Infinity
#float -Infinity

...or something of the sort.

@willglynn

This is satisfactory. I should note that this may not be transparent at the binary-representation-in-RAM level (NaNs carry a sign bit, a signaling flag, and a payload all of which are discarded), but this data loss is explicitly permitted by IEEE 754 under "External character sequences representing zeros, infinities, and NaNs". It's also semantically proper, since floats can still be encoded as floats, even if they're NaN.

@richhickey
Owner

I am in favor of supporting these.
0.NaN 0.Inf -0.Inf ?

@Bronsa

How about simply making [+-]Infinity and NaN "special" symbols like true,false,nil?

@atarzwell

We're running into this bug now, applying the patch from Jira CLJ-1074 seems to resolve it on 1.7 master, but it would be an improvement to not depend on a patched version.

http://dev.clojure.org/jira/browse/CLJ-1074

Is there a fix in the works? Or a more up to date conversation on why this hasn't been addressed?

Thanks,
Andrew

@atarzwell

Andy Fingerhut responded to my similar question on CLJ-1074.

If anyone else runs into this, the tools.reader library handles +/-Infinity and NaN's sanely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.