-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NaNs are weird #750
Comments
So, I took a quick look and this is, oddly enough, intended behavior. 1e+1234 renders to +inf in a double representation. Once we do +inf * 0, we get back NaN.
|
Hmmm.
|
Right. Remember, 1.79769e+308 is the maximum value a double can contain, so 1.79769e+308 * 0 -should- return 0. I'm a little unclear on why 1e+1234 is returning dbl_max instead of inf, though. Maybe that should be the thing to look into. |
Also, it's worth pointing out that the null in my code is still a number, it's just being displayed as null due to how we print jvs. |
This is a "bug" in the constant folding code. See the output of
The code that produces this is:
in We could have the constant folding code special-case multiplication by zero |
Also, if you look at the constant being loaded by LOADK, I bet it's a
number, and a NaN.
I'm not sure how many special cases we'd have to make in
`constant_fold()`, but I'm ok with making some of them (they are
compile-time checks), like this one. But still, it's IEEE754 and
JSON, and when you play on the edges of what's supported by their
intersection, you get weird behavior, because a) IEE754 is weird, and
b) JSON doesn't have a way of representing NaNs.
|
@nicowilliams I can confirm that everything's a NaN, not a null. |
@wtlangford I agree, that's weird and upsetting. Feel fre to fix it.
|
What's the best behavior, then? Does JSON allow +inf and -inf? How do we want to render these numbers that are too great in magnitude to store in double format? |
JSON does not allow NaNs nor infinities. See RFC7159. I dunnob what id's
best here. Perhaps we should see what ECMAScript and others do.
|
Perhaps the current behaviour is as reasonable as any other. We could have
all sorts of number printing options, and print these as strings instead of
null.
|
Using JavaScript-C 1.8.5 2011-03-31:
v8 gives the same results. It seems to me that we'd get results that are both self-consistent and generally conformant with javascript if we treated infinities and NaN as null. This would, however, mean that 1/0 would evaluate to null in contrast to the current behavior, which (misleadingly) shows the result as 1.7976931348623157e+308 --- "misleadingly" because currently 0 *(1/0) => null whereas (0 * 1.7976931348623157e+308) => 0. |
@pkoppstein: That would indicate that what jq did here is correct. What
does JavaScript do when encoding a NaN/infinity in JSON?
FYI, this also happens w/o constant folding, so it's not a bug there. It's
not just a bug, but a workaround for JSON's inability to represent NaNs and
infinities (NaNs -> null, infinities -> min/max).
|
@nicowilliams asked:
Just to be clear, the "bug" that I was referring to is the inconsistency in jq's handling of the various "edge cases", not its handling of any particular case. While we're on the topic of null and arithmetic, it might be worth revisiting the fact that jq dislikes |
@pkoppstein Maybe I'm being dense, but can you list the inconsistencies? Addition of |
@nicowilliams asked:
I think you and @wtlangford have already identified the problem; specifically, you wrote:
That is, the problem is exemplified by this transcript:
Regarding "multiplication by null", I was only pointing out that a case could be made for evaluating One could say, in the spirit of Nihil fit ex nihilo, that if the nothingness that is 0+null is 0, then the nothingness that is 0*null should also be 0. Yes, I realize that one might not want 0 * (1/0) to be 0. But jq already allows the convenience of having 0+null evaluate to 0, and I think the same argument-from-convenience holds for 0*null. |
@pkoppstein But that is an artifact of IEEE754 yielding a NaN in that case. I suppose we could check that we're multiplying by zero, and then always return zero. But... suppose instead of byte-compiling and interpreting that we were coding to LLVM and thus generated highly optimized native object code... each additional special case is one more branch we could not dispense with. I'm quite tempted to say that when you play with IEEE754, you get what you get, and you have to know going in. The alternative for me isn't to special case IEEE754 oddities, but to add an arbitrary precision mode, and that's not happening any time soon. |
On the plus side, I finally added an ieee754 label for this sort of issue! :^) |
Also, recall that we represent NaNs as
How about that. Internally, NaNs are numbers. As to addition of null, the intent there almost certainly ad to do with addition of objects (where one may be null). I'm inclined to leave everything as is, except that I'll consider special-casing multiplication by zero when the other operand is a number and not a NaN or infinity, but my take as to that is to reject it (for the reasons given a couple of comments back). |
@pkoppstein In master now:
I suppose we could add new filters to go with |
The "numbers" filter should, I believe, match the "number" type. Assuming the semantics of the latter is not going to change, maybe a new filter to select the ordinary (finite) numbers could be added. (Names such as "finitenumbers" or "decimals" should be OK.) |
"decimals" won't do (they aren't, not internally). "finites" and "normals" would do, the former for not-infinite and not-NaN numbers, and the latter for finite sub-normals. This would match the C |
@nicowilliams - Did you intend that "finites" would select non-numbers? Currently:
I assume you meant: select(isfinite) |
On Wed, Jun 17, 2015 at 10:31:57PM -0700, pkoppstein wrote:
Nah, just a thinko. Thanks. |
In brief:
In long:
The text was updated successfully, but these errors were encountered: