Jeffrey Sarnoff
Jeffrey Sarnoff

Reputation: 1757

Julia: Is it really possible for rand to throw a zero?

The docs say rand draws iid uniformly distributed values in the half-open unit interval [0,1) which includes zero but is rand ever throwing a zero?

Upvotes: 3

Views: 147

Answers (1)

Jeffrey Sarnoff
Jeffrey Sarnoff

Reputation: 1757

Yes, it is possible for rand() to return zero and rand() does not return one.

Software should be designed to work whether or not iszero(rand()). And it is good practice to provide an appropriate test case. How often does a computer that is continuously generating rand() yield zero? Using very rough estimates: about every six weeks.

Sometimes it may be more appropriate to sample from (0.0, 1.0], omitting zero while permitting one. Here is one way to do that.

zero_as_one(x::T) where {T<:AbstractFloat} =
    ifelse(iszero(x), one(T), x)

rand1(::Type{T}) where {T<:AbstractFloat} =
    zero_as_one(rand(T))

function rand1(::Type{T}, n::I) where {T<:AbstractFloat, I<:Integer}
    n < 1 && throw(ArgumentError("n must be >= 1"))
    n === one(I) && return rand1(T)
    return map(zero_as_one, rand(T, n))
end

Here is a way to sample from (0.0, 1.0), omitting both zero and one.

openrand() = openrand(Float64)

openrand(::Type{T}) where {T<:AbstractFloat} =
    let result = rand(T)
        while iszero(result)
            result = openrand(T)
        end
        result
    end

function openrand(::Type{T}, n::I) where {T<:AbstractFloat, I<:Integer}
    n < 1 && throw(ArgumentError("n must be >= 1"))
    n === one(I) && return openrand(T)
    result = Vector{T}(undef, n)
    for i in 1:n
        result[i] = openrand(T)
    end
    return result
end

In addition to Julia, C, C++, Fortran, Perl, Python, Ruby, and Spreadsheets also use the interval [0.0, 1.0) for uniform random sampling. Matlab and R use (0.0, 1.0). Mathematica uses [0.0, 1.0].


the original thread on discourse

Upvotes: 3

Related Questions