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

1 Like

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 true*float should be a float. Making it Nan would mean that A+false*B 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