# Making my own custom numeric type

**URL:** https://discourse.julialang.org/t/making-my-own-custom-numeric-type/87752
**Category:** New to Julia
**Created:** [September 24, 2022, 4:50pm UTC](https://discourse.julialang.org/t/making-my-own-custom-numeric-type/87752 "2022-09-24T16:50:41Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![ivoytov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ivoytov/32/42480_2.png) [@ivoytov](https://discourse.julialang.org/u/ivoytov)
#### Post date: [September 24, 2022, 4:50pm UTC](https://discourse.julialang.org/t/making-my-own-custom-numeric-type/87752/1 "2022-09-24T16:50:41Z")

</div>

I would like to make my custom Type behave like a numeric type. Ideally I would specify a custom `convert()` function that would do some smart computations to summarize the type’s fields as a single value. What is the cleanest and most design friendly way to do this? I got it working but it seems like some kind of inheritance method would be more reusable.

```julia
julia> struct Ratio
           num::Float64
       end

julia> using Statistics

julia> Ratio[Ratio(1), Ratio(2), Ratio(3)]
3-element Vector{Ratio}:
 Ratio(1.0)
 Ratio(2.0)
 Ratio(3.0)

julia> Statistics.mean(ans)
ERROR: MethodError: no method matching /(::Ratio, ::Int64)
[...]
julia> Statistics.mean(ratios::Vector{Ratio}) = Statistics.mean(getfield.(ratios, :num))

julia> Statistics.mean(ratios)
2.0

```

Ideally I don’t want to create my own duplicate method for every function in Statistics and other modules, but just some way that those functions can see my value as a numeric type natively.

---

<div class="post-metadata">

### Author: ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)
#### Post date: [September 24, 2022, 4:57pm UTC](https://discourse.julialang.org/t/making-my-own-custom-numeric-type/87752/2 "2022-09-24T16:57:15Z")

</div>

You really need to inherit from `Number` or `Real`. But you will still need to define all the method like `/`.

If you want the full interface without so much work, you can use:

> **[GitHub - SimonDanisch/AbstractNumbers.jl: Define your own number types in...](https://github.com/SimonDanisch/AbstractNumbers.jl)**
>
> Define your own number types in Julia super easily! - GitHub - SimonDanisch/AbstractNumbers.jl: Define your own number types in Julia super easily!

---

<div class="post-metadata">

### Author: ![qwerty](https://avatars.discourse-cdn.com/v4/letter/q/4491bb/32.png) [@qwerty](https://discourse.julialang.org/u/qwerty)
#### Post date: [September 24, 2022, 5:51pm UTC](https://discourse.julialang.org/t/making-my-own-custom-numeric-type/87752/3 "2022-09-24T17:51:09Z")

</div>

```julia
struct Ratio
    num::Float64
end

operators = (:+, :*, :/, :-, :÷, :\, :^, :%)

for i in operators
    @eval Base.$(i)(a::Ratio, b::Ratio) = Ratio(($i)(a.num, b.num))
    @eval Base.$(i)(a::Ratio, b::Number) = Ratio(($i)(a.num, b))
    @eval Base.$(i)(a::Number, b::Ratio) = Ratio(($i)(a, b.num))
end

fun = (:sin, :cos, :tan, :cot, :sec, :csc,
       :sinh, :cosh, :tanh, :coth, :sech, :csch, 
       :asin, :acos, :atan, :acot, :asec, :acsc,
       :asinh, :acosh, :atanh, :acoth, :asech, :acsch,
       :sinc, :cosc, :exp, :sqrt, :abs, :log)

for i in fun
    @eval Base.$(i)(a::Ratio) = Ratio(($i)(a.num))
end

sqrt(Ratio(3.0)) #works
sqrt(3.0)

using Statistics

mean([Ratio(1), Ratio(2), Ratio(3)]) # works

```

What do you think of this? is this a good approach for this kind of problem?

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [September 24, 2022, 5:56pm UTC](https://discourse.julialang.org/t/making-my-own-custom-numeric-type/87752/4 "2022-09-24T17:56:49Z")

</div>

You are probably doing more work than necessary. Inheriting from `Real` is probably a good idea.

See [Ratios.jl/Ratios.jl at master · timholy/Ratios.jl · GitHub](https://github.com/timholy/Ratios.jl/blob/master/src/Ratios.jl)

---

<div class="post-metadata">

### Author: ![ivoytov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ivoytov/32/42480_2.png) [@ivoytov](https://discourse.julialang.org/u/ivoytov)
#### Post date: [September 24, 2022, 7:33pm UTC](https://discourse.julialang.org/t/making-my-own-custom-numeric-type/87752/5 "2022-09-24T19:33:01Z")

</div>

Thank you for thoughtful feedback.

1. `AbstractNumbers.jl` - I tried this but ruled it out because it brings in a ton of dependencies that I will not be using.
2. Overloading every operator - I did not try this because it wanted an inheritance approach.
3. My preferred solution just came from copying from the `Ratios.jl` source code:

```julia
julia> struct NewRatio <: Real
       num::Float64
       end

julia> Base.convert(::Type{T}, r::NewRatio) where {T<:Real} = T(r.num)

julia> Statistics.mean([NewRatio(1), NewRatio(2), NewRatio(3)])
2.0

```

---

<div class="post-metadata">

### Author: ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)
#### Post date: [September 25, 2022, 7:07am UTC](https://discourse.julialang.org/t/making-my-own-custom-numeric-type/87752/6 "2022-09-25T07:07:47Z")

</div>

The problem with that approach is you will lose your object at any opration. Usually you will want to do things like keep your type through multiplication by a scalar or addition with itself. Otherwise it doesn’t have much of a use ase.

---

<div class="post-metadata">

### Author: ![ivoytov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ivoytov/32/42480_2.png) [@ivoytov](https://discourse.julialang.org/u/ivoytov)
#### Post date: [September 25, 2022, 12:24pm UTC](https://discourse.julialang.org/t/making-my-own-custom-numeric-type/87752/7 "2022-09-25T12:24:38Z")

</div>

Great point. If your use case is to have a rich record with tons of fields - such as a record for each customer - and you want to have some numerical way to summarize it (like current year purchases), you probably want the record to be destroyed after any computation. Because once you add two customers together, you will have sum of their purchases but you wouldn’t want to have sum of their number of transactions or some sum of their names.

But for something like a stock price daily quote, you might still want - and you could average the high, the low, and so on - to keep the record instance alive.
