# Displaying Rationals

**URL:** <https://discourse.julialang.org/t/displaying-rationals/9475>\
**Category:** General Usage\
**Tags:** numbers, io\
**Created:** [March 3, 2018, 1:50pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475 "2018-03-03T13:50:27Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [March 3, 2018, 1:50pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/1 "2018-03-03T13:50:27Z")

</div>

I have a small complaint about julia. I use all the time matrices of `Rational`s, like

```julia
> 10×10 Array{Rational{Int64},2}:
> 2//1 0//1 0//1 0//1 0//1 0//1 0//1 0//1 0//1 0//1
> 0//1 2//1 0//1 0//1 0//1 0//1 0//1 0//1 0//1 0//1
> 0//1 0//1 4//3 -2//3 2//3 0//1 0//1 2//3 -2//3 -2//3
> 0//1 0//1 -2//3 4//3 2//3 0//1 0//1 2//3 -2//3 -2//3
> 0//1 0//1 2//3 2//3 1//3 1//1 1//1 1//3 2//3 2//3
> 0//1 0//1 0//1 0//1 1//1 1//1 -1//1 -1//1 0//1 0//1
> 0//1 0//1 0//1 0//1 1//1 -1//1 1//1 -1//1 0//1 0//1
> 0//1 0//1 2//3 2//3 1//3 -1//1 -1//1 1//3 2//3 2//3
> 0//1 0//1 -2//3 -2//3 2//3 0//1 0//1 2//3 4//3 -2//3
> 0//1 0//1 -2//3 -2//3 2//3 0//1 0//1 2//3 -2//3 4//3

```

I find it perfectly acceptable that to _input_ a `Rational`, you have  
to write `a//b`. But I find pretty horrible that they are _output_ the same  
way. I would like to see:

```julia
10×10 Array{Rational{Int64},2}:
2 0 0 0 0 0 0 0 0 0
0 2 0 0 0 0 0 0 0 0
0 0 4/3 -2/3 2/3 0 0 2/3 -2/3 -2/3
0 0 -2/3 4/3 2/3 0 0 2/3 -2/3 -2/3
0 0 2/3 2/3 1/3 1 1 1/3 2/3 2/3
0 0 0 0 1 1 -1 -1 0 0
0 0 0 0 1 -1 1 -1 0 0
0 0 2/3 2/3 1/3 -1 -1 1/3 2/3 2/3
0 0 -2/3 -2/3 2/3 0 0 2/3 4/3 -2/3
0 0 -2/3 -2/3 2/3 0 0 2/3 -2/3 4/3

```

As it is, I have the feeling that I must change my glasses whenever I print  
a matrix of `Rationals`. As I understood, you would just have to change (or to  
write a new)

> function Base.display(x::Rational)

to do the trick. Do people think this would be reasonable?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [March 3, 2018, 1:54pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/2 "2018-03-03T13:54:54Z")

</div>

It would be weird to not be able to copy them and have it keep the same type.

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [March 3, 2018, 1:56pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/3 "2018-03-03T13:56:52Z")

</div>

I thought the function `show` and not the function `display` was the one where you should be able to parse back the output. Anyway you cannot copy _as is_ the output: you would have to suppress the summary and add . I certainly would not change the function `show` so you could still copy its output and get the same type.

---

<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:** [March 3, 2018, 3:48pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/4 "2018-03-03T15:48:19Z")

</div>

> [@Jean\_Michel](#):
>
> `Base.display(x::Rational)`

No, you should _not_ overload `display`. Not only would this not affect output as part of a matrix, but the [manual explicitly tells you not to overload `display`](https://docs.julialang.org/en/stable/manual/types/#Custom-pretty-printing-1). To customize output, you use `show`.

One option would be to define a `show` method for `Array{<:Rational}`.

A more permanent solution would be to modify the Base display of `Rational` types. In particular, when a rational value is shown in an array, the array sets the [`:compact` IO context attribute](https://docs.julialang.org/en/stable/manual/networking-and-streams/#IO-Output-Contextual-Properties-1) to `true`. It might be reasonable to show rationals as `p/q` for `:compact=>true` output. In particular, you could submit a JuliaLang/julia PR that modifies the [`show(io, ::Rational) method`](https://github.com/JuliaLang/julia/blob/05ff71f187aa06e51f1eceb1c85cf439d09c790a/base/rational.jl#L62-L66) to something like:

```julia
function show(io::IO, x::Rational)
    show(io, numerator(x))
    print(io, get(io, :compact, false) ? "/" : "//")
    show(io, denominator(x))
end

```

With this change, arrays of rationals will use a single slash, but showing a single rational value in the REPL will still use a double slash. The only problem is that it would affect `repr` of arrays too, meaning the `repr` output would not be parseable to reproduce the input.

Another option would to have a different IO context attribute to suppress the double slash in rational values, which could be set by e.g. `show(io::IO, ::MIME"text/plain", X::AbstractArray)`. Maybe there should be a more general IO context attribute for whether the output needs to be parseable?

I encourage you to try submitting a PR for this, which should be relatively easy (just the code patch above and a test). I can’t guarantee that it will be accepted, but I think there is a reasonable chance that some variant of this change could go in, and it hopefully would be a good experience for you in any case.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [March 3, 2018, 4:17pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/5 "2018-03-03T16:17:58Z")

</div>

But when a rational object is converted to a string, I hope it still retains the `//` because, for example in my packages it is needed to parse rational julia objects into rational values in another programming language, and the behavior of `/` and `//` is supposed to be different when parsing the text of Julia code.

---

<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:** [March 3, 2018, 4:20pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/6 "2018-03-03T16:20:14Z")

</div>

> [@chakravala](#):
>
> parse rational julia objects into rational values in another programming language

That’s why we might want an IO context attribute to indicate whether the `show` output should be parseable etc.

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [March 3, 2018, 4:41pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/7 "2018-03-03T16:41:11Z")

</div>

I would like to only modify the display of `Rational` arrays in the REPL, nothing else since indeed you  
want that all functions usually used for output like `show(x)` and `print(x)` give parseable output. So I guess  
this needs to follow your suggestion to use an `IOContext` set by

> show(io::IO, ::MIME"text/plain", X::AbstractArray)

To have an uncluttered display like I showed above, I would need to modify slightly your code to

```julia
   show(io, numerator(x))
   if get(io, :compact,true) 
        if denominator(x!=1)
           print(io,"/")
           show(io,denominator(x))
        end
   else
       print(io, "//")
       show(io, denominator(x))
   end

```

Do you think that `:compact` is the right io property or another one should be used?

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [March 22, 2020, 3:13pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/8 "2020-03-22T15:13:21Z")

</div>

Here’s an implementation that uses the lighter format in the REPL, without affecting `show(A)` and `repr(A)`:

```julia
import Base.show

function show(io::IO, x::Rational)
    show(io, numerator(x))
    # The default is to not use light format
    if get(io, :lightrationals, false)
        if denominator(x) != 1
            print(io, "/")
            show(io, denominator(x))
        end
    else
        print(io, "//")
        show(io, denominator(x))
    end
end

function show(io::IO, mime::MIME"text/plain", X::AbstractArray{<:Rational})
    # Set light rational format if currently undefined
    if !haskey(io, :lightrationals)
        io = IOContext(io, :lightrationals => true)
    end
    invoke(show, Tuple{IO, MIME"text/plain", AbstractArray}, io, mime, X)
end

```

And in Julia 1.4 it can be then disabled easily 🙂 Just do:

```julia
Base.active_repl.options.iocontext[:lightrationals]=false

```

I didn’t change how scalars are displayed, because that would be confusing I think: nothing would indicate that `2` is actually `2//1` for example. This is not a problem with arrays (even if all rationals happen to be integers) since the type is shown in the summary at the top. But in case someone wants it for scalars too:

```julia
function show(io::IO, ::MIME"text/plain", x::Rational)
    if !haskey(io, :lightrationals)
        io = IOContext(io, :lightrationals => true)
    end
    show(io, x)
end

```

@stevengj do you still think this would make a good PR? If yes, @Jean_Michel would you like to make the PR?

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [March 22, 2020, 10:10pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/9 "2020-03-22T22:10:24Z")

</div>

You can make the PR. I learned some git only very recently and don’t know yet how to make one. Perhaps your key `:lightrationals` could be `:usualrationals` or `:standardrationals` or any other word which suggests that it is the way they are represented in mathematics or in most programming languagues.

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [March 23, 2020, 3:43pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/10 "2020-03-23T15:43:25Z")

</div>

OK I’ll probably make a PR this weekend and put the link here, but feel free to do it first if you want to exercise git skills 🙂

---

<div class="post-metadata">

**Author:** ![thofma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thofma/32/1691_2.png) [@thofma](https://discourse.julialang.org/u/thofma)\
**Post date:** [March 23, 2020, 3:55pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/11 "2020-03-23T15:55:55Z")

</div>

I would not spend time preparing a PR, since I don’t agree that this is a good feature.

For the same reason that `1.0` is not displayed as `1`, we should not add confusion by printing `1//2` as `1/2`. It is horrible if input and output differ for basic number types.

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [March 23, 2020, 6:05pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/12 "2020-03-23T18:05:00Z")

</div>

Let me try to convince you 🙂

I think it’s bad user experience to show arrays with the `0//1` format. Users have to deal with the hard-to-read output every time they print a rational array, just in case they want to copy-paste the values…

And it’s not like all standard array types print in a way that preserves the type on copy-paste… Example:

```julia
julia> rand(Int8, 6, 6)
6×6 Array{Int8,2}:
  -40 55 -2 24 39 69
   71 40 -10 -36 57 44
   48 70 1 -54 -31 93
 -114 118 -46 61 15 -26
   57 124 -44 -124 -99 77
   49 -91 -65 83 -10 101

```

Copy-pasting this will make an Array{Int64} instead of an Array{Int8}.

Now the big difference is that it’s trivial to fix the `Int8` case by pasting inside `Int8[...]`. So what about this:

Let’s define the operator `∕` (“division slash” character in Unicode) as synonym to `//`. Then if we use it to print rational arrays, they will be trivial to copy-paste to the correct type (in the worst case, when you have all integer values, you need to add a `Rational[...]` prefix like for `Int8`).

If `∕` is deemed to close to `/`, we could also use the “big solidus”: `⧸`

What do you think?

---

<div class="post-metadata">

**Author:** ![thofma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thofma/32/1691_2.png) [@thofma](https://discourse.julialang.org/u/thofma)\
**Post date:** [March 23, 2020, 6:09pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/13 "2020-03-23T18:09:25Z")

</div>

Sorry, but using almost identical looking unicode characters for two opposite operations does not sound like an improvement.

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [March 23, 2020, 6:30pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/14 "2020-03-23T18:30:51Z")

</div>

Isn’t 1⧸2 is quite distinct from 1/2? And the `/` and `//` operations are hardly opposite?

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [March 23, 2020, 7:49pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/15 "2020-03-23T19:49:55Z")

</div>

Before instinctively rejecting, please pay more attention to the exact proposal: give a nicer display of `Rationals` _only_ in circumstances where the type is also displayed proeminently.

I personally think that instead of this:

```julia
5×5 Array{Rational{Int64},2}:
 1//2 0//1 0//1 0//1 0//1
 0//1 1//2 0//1 0//1 0//1
 0//1 0//1 1//2 0//1 0//1
 0//1 0//1 0//1 1//2 0//1
 0//1 0//1 0//1 0//1 1//2

```

This is easier to read:

```julia
5×5 Array{Rational{Int64},2}:
 1/2 0 0 0 0
   0 1/2 0 0 0
   0 0 1/2 0 0
   0 0 0 1/2 0
   0 0 0 0 1/2

```

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [March 23, 2020, 8:12pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/16 "2020-03-23T20:12:18Z")

</div>

FWIW, we do essentially this same thing for boolean arrays in 1.2+. I think such a thing could also be reasonable for rationals (but I almost never use them so I don’t have a horse in this race). The implementation is very simple — it’s just a matter of asking the IO stream if it has displayed type information:

[https://github.com/JuliaLang/julia/pull/30575/files#diff-b4267643a238b5a375b3e055817ee6caR567](https://github.com/JuliaLang/julia/pull/30575/files#diff-b4267643a238b5a375b3e055817ee6caR567)

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [March 23, 2020, 9:05pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/17 "2020-03-23T21:05:16Z")

</div>

As I stated earlier, for parsing purposes it will mess things up, since parsing a rational number with a single slash will become a float when evaluated. This will make things confusing because when you write code with something like `1/2` it becomes a float if you are parsing, while it might be the display of a rational. This means that writing a number in code and parsing it from an output will give different results.

If you really want to change it, then the default has to be changed so that `1/2` is rational by default when writing code also. If you’re gonna change it, the entire syntax should be switched over, going only half way and doing it only for the display will lead to confusion.

Since this is a breaking change, it has to wait until 2.0

It would break code which relies on parsing rationals.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [March 23, 2020, 9:11pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/18 "2020-03-23T21:11:05Z")

</div>

> [@chakravala](#):
>
> Since this is a breaking change, it has to wait until 2.0
> 
> It would break code which relies on parsing rationals.

Just to be clear, tweaking the printed output in the REPL for some Base type is not considered a breaking change (and tends to happen in every minor release)…

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [March 23, 2020, 9:13pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/19 "2020-03-23T21:13:27Z")

</div>

In my post I am talking about also changing the behavior of `/` function to make rationals, so that is a breaking change, since I recommend going all the way and changing the `/` function instead of going half way to only change the display. That would be breaking.

Either go all the way with it or dont change it.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [March 23, 2020, 9:20pm UTC](https://discourse.julialang.org/t/displaying-rationals/9475/20 "2020-03-23T21:20:02Z")

</div>

You seem to be missing the part about this only having an effect when printing lots of rationals inside a well-typed container — just like how we don’t display `true` and `false` as `1` and `0` generally. This is a limited case with lots of repeats; and the superfluous information can certainly get in the way.

At a minimum, it seems like it could be worthwhile to avoid `//1` for whole numbers.

[Next page](https://discourse.julialang.org/t/displaying-rationals/9475.md?page=2)
