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
?
Because changing false
by true
we get always the same result: NaN
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
?
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
Regarding false as strong zero, see Knuth’s writings at [math/9205211] Two notes on notation.
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?
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.
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?
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.
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