Skip to content

You can convert infinity to an integer (Float16) #49422

@yurivish

Description

@yurivish

Julia’s convert function is designed to let users safely convert a floating-point integers such as 2.0 into the equivalent Int value, such as 2. It is documented to throw an error if given a non-integer value:

If T is an Integer type, an InexactError will be raised if x is not representable by T, for example if x is not integer-valued, or is outside the range supported by T.

However, it will silently convert infinity into an integer if you give it -Inf16:

julia> isinteger(-Inf16) # infinity is not an integer
false

julia> convert(Int, -Inf16) # but Julia 1.6 – 1.9rc2 will happily turn it into one
-9223372036854775808

This behavior only occurs for 16-bit negative infinity:

julia> convert(Int, -Inf32)
ERROR: InexactError: Int64(-Inf)

julia> convert(Int, -Inf64)
ERROR: InexactError: Int64(-Inf)

You can convert infinity into an Int32, Int64, or Int128 and it will take on a different integer value for each:

julia> Int32(-Inf16)
-2147483648

julia> Int64(-Inf16)
-9223372036854775808

julia> Int128(-Inf16)
0

I debugged this and found that it happens because convert(Int, x) calls Int(x), which has an bug that causes it to mess up the validity check for -Inf16:

function (::Type{$Ti})(x::$Tf)
    if ($(Tf(typemin(Ti))) <= x <= $(Tf(typemax(Ti)))) && (round(x, RoundToZero) == x)
        return unsafe_trunc($Ti,x)
    else
        throw(InexactError($(Expr(:quote,Ti.name.name)), $Ti, x))
    end
end

The comparison on the second line produces the incorrect behavior, because Float16(typemin(Int)) == -Inf16:

julia> Float16(typemin(Int64))
-Inf16

julia> Float32(typemin(Int64))
-9.223372f18

julia> Float64(typemin(Int64))
-9.223372036854776e18

Which causes the interval check to succeed:

Float16(typemin(Int)) <= x < Float16(typemax(Int)))

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIndicates an unexpected problem or unintended behaviorfloat16

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions