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
``````
1 Like

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`?

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)
``````

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