diff --git a/base/intfuncs.jl b/base/intfuncs.jl index a6f6ea05efe41..5079989881aa9 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -744,12 +744,22 @@ julia> digits!([2,2,2,2,2,2], 10, base = 2) ``` """ function digits!(a::AbstractVector{T}, n::Integer; base::Integer = 10) where T<:Integer - base < 0 && isa(n, Unsigned) && return digits!(a, convert(Signed, n), base = base) 2 <= abs(base) || throw(ArgumentError("base must be ≥ 2 or ≤ -2, got $base")) hastypemax(T) && abs(base) - 1 > typemax(T) && throw(ArgumentError("type $T too small for base $base")) + isempty(a) && return a + skipfirst = false + if base < 0 && n isa Unsigned + d = mod(n, -base) + n = -signed(fld(n, -base)) + skipfirst = true + end + for i in eachindex(a) - if base > 0 + if skipfirst + skipfirst = false + a[i] = d + elseif base > 0 a[i] = rem(n, base) n = div(n, base) else diff --git a/test/intfuncs.jl b/test/intfuncs.jl index b060bc69686b2..37033bde31fa4 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -179,11 +179,18 @@ end @test digits(5, base = 3) == [2, 1] @testset "digits/base with negative bases" begin - @testset "digits(n::$T, base = b)" for T in (Int, UInt, BigInt, Int32) + @testset "digits(n::$T, base = b)" for T in (Int, UInt, BigInt, Int32, UInt32) @test digits(T(8163), base = -10) == [3, 4, 2, 2, 1] if !(T<:Unsigned) @test digits(T(-8163), base = -10) == [7, 7, 9, 9] end + if T !== BigInt + b = rand(-32:-2) + for n = T[rand(T), typemax(T), typemin(T)] + # issue #29183 + @test digits(n, base=b) == digits(signed(widen(n)), base=b) + end + end end @test [string(n, base = b) for n = [-10^9, -10^5, -2^20, -2^10, -100, -83, -50, -34, -27, -16, -7, -3, -2, -1,