About NaN, 0/0 and false

Why…

NaN*(0/0)*false gives 0.0,

(0/0)*NaN*false gives -0.0,

and:

false*(0/0)*NaN
false*NaN*(0/0)
NaN*false*(0/0)
(0/0)*false*NaN all give NaN? :thinking:

Because changing false by true we get always the same result: NaN

Interesting, it seems to be intentional.

# make `false` a "strong zero": false*NaN == 0.0
function *(x::Bool, y::T)::promote_type(Bool,T) where T<:AbstractFloat
    return ifelse(x, y, copysign(zero(y), y))
end
1 Like

Cf Inconsistency of NaN.

Regarding false as strong zero, see Knuth’s writings at https://arxiv.org/abs/math/9205211.

5 Likes

Ok, but how would you explain -0.0 instead of 0.0 and the cases when we get NaN?

Follow my first link and read the explanations from last time you asked that question.

But how does that explain the cases when we get NaN?

Your four last cases all boil down to false (strong zero) times anything becoming an ordinary 0, and ordinary 0 times NaN becoming NaN. Well, that and left-associativity of multiplication.

Multiplication happens left to right. False* Nan is 0 (or negative 0). Thus multiplying that by a Nan yields a Nan.

julia> false * NaN
0.0

julia> NaN * false
0.0

Saying I’m surprising with this is to say the least.

For me ANY operation involving a NaN must be a NaN

See Knuth’s paper linked by @GunnarFarneback , for me after thinking it up it makes sense to treat false as super strong 0 to suport Iverson’s bracket convention.

Pop-quiz, in C++ what would the following result in:

std::max(Nan,x) 
std::max(x,NaN) 
fmax(Nan,x)
fmax(x,NaN)

And what about in Julia?

2 Likes

I’ve not present what they do in C++ (I deal quite a bit with NaNs in C but use isnan() to detect and deal with them).

In Julia they do the right thing

julia> max(NaN,8.0)
NaN

julia> max(NaN,8.0,NaN)
NaN

julia> maximum([1.1 5 7 9 NaN])
NaN

but the right thing is not always what we want. For example, for the maximum I would like to have a way to skip the NaNs. If they were missing one could use the skipmissing function but did not find an equivalent for NaNs.

I wonder if I had to little or too much coffee to parse this.

3 Likes

OK, I’ll give some sugar. More often than not one wants that maximum([1.1 5 7 9 NaN]) returns 9 (which, BTW, is what Matlab does). But given the definition of NaN that, like Midas, where it touches transforms every number into a a NaN, returning NaN is the right thing.

max([1.1 5 7 9 NaN],,‘includenan’)

ans =

NaN

There have been a hundred questions about how Julia handles (or, rather, does not handle) NaN and missing with regard to functions like sum, max, etc.

Every single time the conclusion is that it is up to the programmer to deal with them, and that functions like max should in-fact return NaN if one or more of its inputs have that value.

Discussion derived but that was not the point before. I just manifested my surprise that

false * NaN
0.0

It’s only me?

1 Like

What do you think it should be the 3 semi-plausible outcomes are false, 0, and Nan. It can’t be false since truefloat should be a float. Making it Nan would mean that A+falseB is not always equal to A, which would break sparse matrices. Thus 0.0 is the best answer.

1 Like

Once you accept the multiplication between a boolean and a floating point number, maybe you can also accept that it gives a particular, documented, result

4 Likes