cognitect / transit-format

A data interchange format.
1.87k stars 36 forks source link

-9223372036854775808 >=53 && < 64 bit numbers uses ~i instead of ~n #28

Closed delaneyj closed 9 years ago

delaneyj commented 9 years ago

-9223372036854775807 should be the last number ((2^63)-1 due to the signed bit) that shows up with an ~i prefix but ~i-9223372036854775808 appears in "ints_interesting_neg.json" instead of ~n-9223372036854775808. This is probably related to https://github.com/cognitect/transit-format/issues/26.

jlouis commented 9 years ago

A two's complement integer uses 0000…000₂ to represent the value 0. This "uses up" one of the "positives numbers" for 0, which means there will be one extra value in the negatives. OCaml:

utop # (Int64.max_int, Int64.min_int);;
- : int64 * int64 = (9223372036854775807, -9223372036854775808)

From C's limits.h:

/* Minimum and maximum values a `signed long int' can hold.  */
#  if __WORDSIZE == 64
#   define LONG_MAX     9223372036854775807L
#  else
#   define LONG_MAX     2147483647L
#  endif
#  define LONG_MIN      (-LONG_MAX - 1L)

It is different from the 53 bit cutoff point in a crucial way, since the 53-bit issue is with floating point numbers which do not use a two's complement representation. So there, the worry is real, but it shouldn't be on this string representation.

If your language disallows -LONG_MAX - 1L, then it's worthy of discussion since other languages might have decided to the same, for instance to make something like math:abs(LONG_MIN) work.

(also, please verify I'm right here. It's so easy to mess up bitwise stuff)

delaneyj commented 9 years ago

C#'s long.MinValue/Max value matched what your are saying. Sorry I've never really dealt with bitlevel stuff on negative numbers. Thanks for the help and now all my tests pass!