# Overwriting matrix elements of a different type

**URL:** <https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572>\
**Category:** New to Julia\
**Tags:** convert\
**Created:** [October 31, 2022, 4:15pm UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572 "2022-10-31T16:15:50Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![chadagreene](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chadagreene/32/34924_2.png) [@chadagreene](https://discourse.julialang.org/u/chadagreene)\
**Post date:** [October 31, 2022, 4:15pm UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/1 "2022-10-31T16:15:51Z")

</div>

Suppose I have this matrix:

```julia
M = [1 2 3; 4 5 6];

```

The type of `M` is Int64, but now I want to update one of the values to a non-integer:

```julia
M[1] = pi

```

Of course, the above just produces this error:

```julia
ERROR: MethodError: no method matching Int64(::Irrational{:π})
Closest candidates are:
  (::Type{T})(::T) where T<:Number at boot.jl:772
  (::Type{T})(::AbstractChar) where T<:Union{Int32, Int64} at char.jl:51
  (::Type{T})(::AbstractChar) where T<:Union{AbstractChar, Number} at char.jl:50
  ...
Stacktrace:
 [1] convert(#unused#::Type{Int64}, x::Irrational{:π})
   @ Base ./number.jl:7
 [2] setindex!(A::Matrix{Int64}, x::Irrational{:π}, i1::Int64)
   @ Base ./array.jl:966
 [3] top-level scope
   @ REPL[21]:1

```

So what’s the recommended method of updating elements in a matrix that may be of a different type than the matrix itself?

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [October 31, 2022, 4:20pm UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/2 "2022-10-31T16:20:20Z")

</div>

It’s not possible unless the matrix’s type is supertype. There’s lots of reasons it wouldn’t work:

1. Different types might require different amounts of memory.
2. Knowing the type of each element now isn’t a property of the array, but of the element, so every element has to carry a type tag.

If you plan to use arrays this way, probably best to use `Matrix{Any}`.

---

<div class="post-metadata">

**Author:** ![chadagreene](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chadagreene/32/34924_2.png) [@chadagreene](https://discourse.julialang.org/u/chadagreene)\
**Post date:** [October 31, 2022, 4:28pm UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/3 "2022-10-31T16:28:52Z")

</div>

Well, one way to accomplish the goal is to convert `M` manually and then update the elements, like

```julia
M = [1 2 3; 4 5 6];
M = convert(Matrix{Float64},M);
M[1] = pi; 

```

Is there a more elegant solution?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 31, 2022, 4:32pm UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/4 "2022-10-31T16:32:16Z")

</div>

Be careful that those Ms are not the same matrix, meaning that mutations in the later won’t be reflected in the previous M, if for instance it was an input of a function, intending to mutate it.

You have just assigned the M label to two different matrices.

---

<div class="post-metadata">

**Author:** ![chadagreene](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chadagreene/32/34924_2.png) [@chadagreene](https://discourse.julialang.org/u/chadagreene)\
**Post date:** [October 31, 2022, 4:38pm UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/5 "2022-10-31T16:38:04Z")

</div>

Whoa whoa whoa, so I now have _two_ `M` matrices? I thought I effectively deleted the first one when I converted it to Float64 and called it by the same name.

The Julia workspace only shows one `M`, so where’d the first one go?

 ![Screen Shot 2022-10-31 at 9.35.21 AM](https://global.discourse-cdn.com/julialang/original/3X/a/d/addf190b733c572beaf59cd6a7ae00dca8df8712.png)

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [October 31, 2022, 4:45pm UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/6 "2022-10-31T16:45:23Z")

</div>

You only have one matrix, Leandro’s point was that if you do this in a function, the input would not be modified as you are allocating a new matrix when you change the type:

```julia
julia> function change_element(m)
           m = float.(m)
           m[1, 1] = π
           m
       end
change_element (generic function with 1 method)

julia> x = [1 2; 3 4]
2×2 Matrix{Int64}:
 1 2
 3 4

julia> change_element(x)
2×2 Matrix{Float64}:
 3.14159 2.0
 3.0 4.0

julia> x
2×2 Matrix{Int64}:
 1 2
 3 4

```

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [October 31, 2022, 4:52pm UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/7 "2022-10-31T16:52:02Z")

</div>

Setfield.jl can do this:

```julia
julia> using Setfield

julia> x = [1 2; 3 4]
2×2 Matrix{Int64}:
 1 2
 3 4

julia> @set! x[1] = pi;

julia> x
2×2 Matrix{Float64}:
 3.14159 2.0
 3.0 4.0

```

Note that this is just makes a copy of the matrix for you promoted to Float64 before setting the element, so depending on your usecase, using a `Matrix{Real}` or something like that could be better.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 31, 2022, 4:55pm UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/8 "2022-10-31T16:55:47Z")

</div>

> [@chadagreene](#):
>
> I thought I effectively deleted the first one

What you did is to assign the label `M` to a new matrix. The previous matrix, if not referenced by any other label, can’t be accessed anymore, and will be garbage-collected when GC runs.

If you do have another label/reference to that matrix, it is still there, and is not mutated:

```julia
julia> a = [1 2; 3 4]
2×2 Matrix{Int64}:
 1 2
 3 4

julia> m = a;

julia> m = convert(Matrix{Float64}, m);

julia> m[1,1] = π
π = 3.1415926535897...

julia> m
2×2 Matrix{Float64}:
 3.14159 2.0
 3.0 4.0

julia> a
2×2 Matrix{Int64}:
 1 2
 3 4

```

(note also that `Setfield` is not doing anything different from this). The point is: you cannot _mutate_ the field of a matrix to a Float64 whose memory layout is such to store only Int64. You have to create a new matrix, or set the matrix to support both types from start, either using `Matrix{Real}[]` or `Matrix{Uniont{Int,Float64}}`, or similar, but that comes with an important performance penalty, which might be relevant or not depending on what you are doing.

---

<div class="post-metadata">

**Author:** ![PeterSimon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petersimon/32/25193_2.png) [@PeterSimon](https://discourse.julialang.org/u/PeterSimon)\
**Post date:** [November 2, 2022, 3:09am UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/9 "2022-11-02T03:09:12Z")

</div>

> [@chadagreene](#):
>
> Is there a more elegant solution?

Not sure whether or not this is elegant, but it does reuse the same matrix:

```julia
function int2float(a::Array{Int})
    maxa = 2^53
    for i in eachindex(a)
        abs(a[i]) > maxa && error("a[", i, "] = ", a[i], " not exactly representable by Float64")
        a[i] = reinterpret(Int, float(a[i]))
    end
    return reinterpret(Float64, a)
end

```

It’s used like this:

```julia
julia> x = [1 2 3; 4 5 6]
2×3 Matrix{Int64}:
 1 2 3
 4 5 6

julia> y = int2float(x)
2×3 reinterpret(Float64, ::Matrix{Int64}):
 1.0 2.0 3.0
 4.0 5.0 6.0

julia> y[1] = pi; y
2×3 reinterpret(Float64, ::Matrix{Int64}):
 3.14159 2.0 3.0
 4.0 5.0 6.0

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [November 2, 2022, 3:51am UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/10 "2022-11-02T03:51:19Z")

</div>

I legit think OP might just be looking for this:

```julia
julia> M = Float64[1 2 3; 4 5 6];

julia> M[1] = pi;

julia> M
2×3 Matrix{Float64}:
 3.14159 2.0 3.0
 4.0 5.0 6.0

```

i.e. the solution is to initialize the Matrix with a more appropriate type (technically, the one that promotes to

```julia
julia> promote_type(Int64, Float64, Irrational)
Float64

```

)

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [November 2, 2022, 8:23am UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/11 "2022-11-02T08:23:25Z")

</div>

> [@PeterSimon](#):
>
> `function int2float(a::Array{Int})`

This is actually quite a fun solution, but I think it requires a bit of explanation.

I also agree with @jling that it’s probably an XY-problem.

---

<div class="post-metadata">

**Author:** ![PeterSimon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petersimon/32/25193_2.png) [@PeterSimon](https://discourse.julialang.org/u/PeterSimon)\
**Post date:** [November 2, 2022, 4:46pm UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/12 "2022-11-02T16:46:45Z")

</div>

> [@DNF](#):
>
> This is actually quite a fun solution, but I think it requires a bit of explanation.

Thanks! Here’s the explanation: `2^53` is the largest integer for which it and all smaller integers can be exactly represented by the 52-bit mantissa used in a `Float64`, as discussed in [this post](https://stackoverflow.com/questions/1848700/biggest-integer-that-can-be-stored-in-a-double). So, after this test, the function first replaces each integer element of `a` by another integer whose interpretation as a `Float64` would produce the same value, then returns an interpretation of the matrix as those `Float64` values. However, as discussed in the above link, there are some integers greater than `2^53` which can also be exactly represented by `Float64`s, and these are not allowed by the function I posted previously. The version below works for any integer exactly representable in `Float64` and is probably a little clearer. Warning: with either version of the function, the original `Int` array is modified so that it can’t be usefully referenced through its original binding.

```julia
function int2float(a::Array{Int})
    for i in eachindex(a)
        aif = float(a[i])
        a[i] == aif || error("a[", i, "] = ", a[i], " not exactly representable by Float64")
        a[i] = reinterpret(Int, aif)
    end
    return reinterpret(Float64, a)
end

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [November 2, 2022, 4:58pm UTC](https://discourse.julialang.org/t/overwriting-matrix-elements-of-a-different-type/89572/13 "2022-11-02T16:58:34Z")

</div>

> [@PeterSimon](#):
>
> Here’s the explanation: `2^53` is the largest integer for which it and all smaller integers can be exactly represented by the 52-bit mantissa used in a `Float64`

You can also use the function `maxintfloat`:

```julia
julia> maxintfloat(Float64)
9.007199254740992e15

julia> maxintfloat(Float64) == 2^53
true

```

But I tend to think this is a distraction—if you want to store a floating-point value in _any_ element of the array, then you are probably willing to deal with roundoff errors if you are going to do any calculation at all with the elements. Presumably @chadagreen should have used a floating-point matrix to start with.

For people coming from Matlab, the Matlab arrays are floating-point by default, and Matlab will silently allocate complex-number storage for you if you assign a complex number, and will silently grow the array if you assign past the end of the array. (For people coming from Python, the default Python lists are equivalent to `Any[...]` arrays in Julia.). Julia arrays, in contrast, default to the type of the elements you initialize them with (unless you explicitly specify another type), and Julia will never convert the whole array to another type or silently resize it without you explicitly requesting it. So, you should think a bit more carefully in Julia about what type of elements you want when the array is created.

Julia is pretty powerful — you can play all kinds of games to optimize code, re-use storage (even using storage from an array of `Int64` to store an array of `Float64`, as in the `int2float` function above), and so forth. But in most cases the simpler techniques suffice, and on Julia Discourse we can sometimes confuse people by immediately showing off all the tricks.
