# Get output of trig function as a multiple of pi?

**URL:** https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229
**Category:** General Usage
**Tags:** numbers
**Created:** [November 16, 2020, 2:42pm UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229 "2020-11-16T14:42:27Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![GuidoDipietro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/guidodipietro/32/18565_2.png) [@GuidoDipietro](https://discourse.julialang.org/u/GuidoDipietro)
#### Post date: [November 16, 2020, 2:42pm UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/1 "2020-11-16T14:42:27Z")

</div>

Hi there, I’ve been using the Julia REPL a lot as a calculator for my day to day life (as a student of engineering, this is really helpful, and definitely much more comfortable to use than a Casio calc for simple things, or using some other REPL like Python’s).

But I’ve found something that I’d like to know a workaround for.  
For example, if I type something like `arccos(-0.5)` on my Casio (in RAD), I’d get (2/3)pi as a result.  
However, in Julia, I get the approximate rational result for that as I enter `acos(-0.5)` on the REPL (I get 2.0943951023931957 which is a very great approximation of the result, but not exact).

I wonder, is there a way to get the outcome as a multiple of _pi_ for these cases, or maybe a function that does this afterwards that I can pipe to this result?  
Of course I could just divide the result by pi and do that by hand but this is not something I’m willing to do 😛

Thank you everyone!

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [November 16, 2020, 2:51pm UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/2 "2020-11-16T14:51:09Z")

</div>

There is no `acospi`, but you can work with `acosd` and convert degrees.

However, it is unclear what you really want here, since `2/3` is not representable as a `Float64`. If you want rationals, maybe

```julia
julia> rationalize(acosd(-0.5)/180)
2//3

```

---

<div class="post-metadata">

### Author: ![GuidoDipietro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/guidodipietro/32/18565_2.png) [@GuidoDipietro](https://discourse.julialang.org/u/GuidoDipietro)
#### Post date: [November 16, 2020, 3:00pm UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/3 "2020-11-16T15:00:29Z")

</div>

I’d just like to get some output like this

```julia
acos( cos(pi/2) )
pi/2

asin(sin((1/6)pi))
pi/6

```

So, I know `pi/2` is no existing type in Julia (or so I believe), neither is `pi//2` because pi is obviously irrational, so perhaps just having the fractional part and knowing that it is `* pi` would do.

So like (imagining an `acospi` function)

```julia
acospi(cos(pi/3))
1//3 (times pi)

```

Your solution is pretty good, but perhaps a bit long to type (though it works well as a ‘quick fix’ for my problem), thanks for that!

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [November 16, 2020, 4:10pm UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/4 "2020-11-16T16:10:18Z")

</div>

These are impossible in general. Out of the very few special cases you give the intermediate result already cannot be exactly represented. If for whatever reason you **really** need fraction representation of angle, you should use symbolic calculation instead and you will not be able to find anything like that in the base math functions.

---

<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: [November 16, 2020, 4:45pm UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/5 "2020-11-16T16:45:37Z")

</div>

Well, just for fun you could do this:

```julia
julia> struct PiF
         x
       end

julia> function Base.show(io :: IO, x :: PiF) 
         y = rationalize(x.x/π)
         println("($(y.num)/$(y.den))π")
       end

julia> PiF(acos(cos(pi/2)))
(1/2)π

julia> PiF(asin(sin(π/6)))
(1/6)π

```

But I am not sure how useful is that. It is pretty though 🙂

Or even simpler, just define the function:

```julia
julia> function pifrac(x)
         y = rationalize(x/π)
         println("($(y.num)/$(y.den))π")
       end
pifrac (generic function with 1 method)

julia> pifrac(asin(sin(π/6)))
(1/6)π

```

---

<div class="post-metadata">

### Author: ![GuidoDipietro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/guidodipietro/32/18565_2.png) [@GuidoDipietro](https://discourse.julialang.org/u/GuidoDipietro)
#### Post date: [November 16, 2020, 7:59pm UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/6 "2020-11-16T19:59:02Z")

</div>

Lovely solution!

Thank you all for the replies, I’ll probably just use the float approximation instead, hahaha.

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [November 16, 2020, 10:31pm UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/7 "2020-11-16T22:31:51Z")

</div>

This is a very nice solution! One might want to define a tolerance in **rationalize**. As is, the code outputs:

```julia
julia> PiF(acos(cos(pi/17)))
(235482333457281/4003199668773778)π

```

But if one defines some tolerance, say:

```julia
y = rationalize(x.x/π, tol=10*eps(x.x))

```

the output becomes:

```julia
julia> PiF(acos(cos(pi/17)))
(1/17)π

```

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [November 18, 2020, 4:08am UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/8 "2020-11-18T04:08:00Z")

</div>

Note that these are just introducing more errors to the calculation in general. Unless your actual goal is to do approximate calculation that somehow want to use fractions as much as possible or you somehow know that all the numbers you’ll ever deal with are fractions with smal denominators you should not use any of these.

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [November 18, 2020, 11:07am UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/9 "2020-11-18T11:07:22Z")

</div>

This reminds me an old university joke.  
A businessman hires a mathematician, a computer scientist and a physicist in order to be able to win all the trifecta horse race bets.  
The mathematician after long weeks of lemmas, theorems and conjectures, concludes that the problem is formally irresolvable. Then, the computer scientist takes up the challenge on a supercomputer and after having written quantities of algorithms he happily announces that it will take just a few hundred years to calculate the result of each trifecta. The physicist, with a smile on his face, informs his eminent colleagues that he has the solution. He approaches a blackboard and while drawing a curve he begins by saying: “Let us approximate the horse by a perfect sphere…”

---

<div class="post-metadata">

### Author: ![liuyxpp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/liuyxpp/32/9870_2.png) [@liuyxpp](https://discourse.julialang.org/u/liuyxpp)
#### Post date: [April 13, 2021, 3:39am UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/10 "2021-04-13T03:39:04Z")

</div>

I find this solution pretty useful. Can anyone tell me how to suppress display the type name PiF when there is an array of PiF objects? example:

```julia
julia > PiFrac.([2π/3,π/3,π/4])
3-element Vector{Scattering.PiFrac}:
 2π/3
 π/3
 π/4

```

This is fine. Now suppose there is a UnitCell type which has a field of an array of angles

```julia
struct UnitCell
    edges
    angles
end

Base.show(io::IO, uc::UnitCell) = print(io, typeof(uc), " with edges ", uc.edges, " and angles ", PiFrac.(uc.angles))

```

```julia
julia > UnitCell([1.0,1.0,1.0], [π/2, π/2, π/2])
UnitCell{3, Float64} with edges [1.0, 1.0, 1.0] and angles PiFrac[π/2, π/2, π/2]

```

I would like to get rid of “PiFrac” before the bracket “[” just like [1.0, 1.0, 1.0] without “Float64”?

---

<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: [April 13, 2021, 11:48am UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/11 "2021-04-13T11:48:33Z")

</div>

I think the way is to overload `print`:

```julia
julia> struct PiF
         x
       end

julia> function Base.show(io::IO, x::PiF) 
         y = rationalize(x.x/π)
         print("($(y.num)/$(y.den))π")
       end

julia> function Base.print(stdout::IO,x::AbstractVector{PiF})
         print("[")
         for i in firstindex(x):lastindex(x)-1
           print("$(x[i]), ")
         end
         print(" $(x[end])]")
       end

julia> println(v)
[(2/3)π, (1/3)π, (1/4)π]

julia> print(v)
[(2/3)π, (1/3)π, (1/4)π]

```

---

<div class="post-metadata">

### Author: ![liuyxpp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/liuyxpp/32/9870_2.png) [@liuyxpp](https://discourse.julialang.org/u/liuyxpp)
#### Post date: [April 13, 2021, 12:35pm UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/12 "2021-04-13T12:35:42Z")

</div>

Thanks! Inspiring by your idea, I have read through the Base source code for printing Array. I found the following more short solution:

```julia
Base.show(io::IO, xs::AbstractVector{PiF}) = Base.show_delim_array(io, xs, "[", ",", "]", false)

```

Edit: to be complete, following is my full solution. Note that (1/2)π is shown as π/2 instead. And (1/1)π is shown as π, (2/1)π is shown as 2π, etc.

```julia
"""
A custom type for pretty display of angles in radian.
"""
struct PiFrac
    θ
end

function Base.show(io::IO, x::PiFrac)
    y = rationalize(x.θ/π, tol=100*eps(x.θ))
    if y.num == 1
        y.den == 1 ? print(io, "π") : print(io, "π/$(y.den)")
    else
        y.den == 1 ? print(io, "$(y.num)π") : print(io, "$(y.num)π/$(y.den)")
    end
end

Base.show(io::IO, ::MIME"text/plain", x::PiFrac) = show(io, x)

Base.show(io::IO, xs::AbstractVector{PiFrac}) = Base.show_delim_array(io, xs, "[", ",", "]", false)

```

```julia
julia> PiFrac.([π/2 3π/2 2π; 2π/3 π/4 π])
2×3 Matrix{Scattering.PiFrac}:
 π/2 3π/2 2π
 2π/3 π/4 π

```

---

<div class="post-metadata">

### Author: ![anj1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/anj1/32/31235_2.png) [@anj1](https://discourse.julialang.org/u/anj1)
#### Post date: [November 30, 2021, 8:31pm UTC](https://discourse.julialang.org/t/get-output-of-trig-function-as-a-multiple-of-pi/50229/13 "2021-11-30T20:31:21Z")

</div>

Have a look at [https://github.com/anj1/AlgebraicNumbers.jl/tree/anj1\_log\_alg](https://github.com/anj1/AlgebraicNumbers.jl/tree/anj1_log_alg), it does exactly what you’re looking for 🙂

```julia
julia> acos_alg(AlgebraicNumber(-1//2))
2//3

```

And better still, it actually uses exact calculation, not approximate calculation using `rationalize`, so it will always give the correct result.  
(Internally it works via representation using minimal polynomials)
