Skip to content

Missing edge case when converting Float to UInt #43882

Closed
@mchristianl

Description

@mchristianl

Hi,

I found some strange behavior hat might be a missing edge case when converting typemax(UInt64) from-and-to Float64.

In the following code, the neighbouring numbers of Float64(typemax(UInt64)) are converted to UInt64 again. The bigger such neighbours throw an InexactError, where the smaller ones perform the conversion.

But UInt64(Float64(typemax(UInt64))) (case b2 below) does something strange

a2 = typemax(UInt64) # 0xffffffffffffffff

f1 =                     nextfloat(Float64(a2))   # 1.8446744073709556e19
f2 =                               Float64(a2)    # 1.8446744073709552e19
f3 =                     prevfloat(Float64(a2))   # 1.8446744073709550e19
f4 =           prevfloat(prevfloat(Float64(a2)))  # 1.8446744073709548e19
f5 = prevfloat(prevfloat(prevfloat(Float64(a2)))) # 1.8446744073709545e19
                                                  # ...

b1 = UInt64(f1) #       InexactError ✓
b2 = UInt64(f2) # 0x8000000000000000 ↯↯↯
b3 = UInt64(f3) # 0xfffffffffffff800 ✓
b4 = UInt64(f4) # 0xfffffffffffff000 ✓
b5 = UInt64(f5) # 0xffffffffffffe800 ✓
                # ...

there is a similar issue with Float32

a2 = typemax(UInt32) # 0xffffffff

f1 =                     nextfloat(Float32(a2))   # 4.2949680f9
f2 =                               Float32(a2)    # 4.2949673f9
f3 =                     prevfloat(Float32(a2))   # 4.2949670f9
f4 =           prevfloat(prevfloat(Float32(a2)))  # 4.2949668f9
f5 = prevfloat(prevfloat(prevfloat(Float32(a2)))) # 4.2949665f9
                                                  # ...

b1 = UInt32(f1) # InexactError ✓
b2 = UInt32(f2) #  0x00000000 ↯↯↯
b3 = UInt32(f3) #  0xffffff00 ✓
b4 = UInt32(f4) #  0xfffffe00 ✓
b5 = UInt32(f5) #  0xfffffd00 ✓
                # ...

and a bit worse situation with Float16

a2 = typemax(UInt16) # 0xffff

f1 =                     nextfloat(Float16(a2))   #           Inf16 ☝️🧐
f2 =                               Float16(a2)    #           Inf16 ☝️🧐
f3 =                     prevfloat(Float16(a2))   # Float16(6.550e4)
f4 =           prevfloat(prevfloat(Float16(a2)))  # Float16(6.547e4)
f5 = prevfloat(prevfloat(prevfloat(Float16(a2)))) # Float16(6.544e4)
                                                  # ...

b1 = UInt16(f1) # 0x0000 ↯↯↯
b2 = UInt16(f2) # 0x0000 ↯↯↯
b3 = UInt16(f3) # 0xffe0 ✓
b4 = UInt16(f4) # 0xffc0 ✓
b5 = UInt16(f5) # 0xffa0 ✓
                # ...

Is this intended, or just on my system? I would expect the ↯↯↯-cases to throw an inexact error.

Julia Version 1.7.1
Commit ac5cc99908* (2021-12-22 19:35 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.0 (ORCJIT, skylake)
Environment:
  JULIA_LOAD_PATH = /usr/share/gmsh/api/julia/:
  JULIA_EDITOR = code
  JULIA_NUM_THREADS = 4

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIndicates an unexpected problem or unintended behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions