# Is there a dedicated function computing m::Int = log(b, b^m)?

**URL:** https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776
**Category:** General Usage
**Tags:** base
**Created:** [November 4, 2022, 2:02pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776 "2022-11-04T14:02:07Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![dmetivie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmetivie/32/6926_2.png) [@dmetivie](https://discourse.julialang.org/u/dmetivie)
#### Post date: [November 4, 2022, 2:02pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/1 "2022-11-04T14:02:08Z")

</div>

I want to compute the integer `m` in `m = log(b, y)` for `b` integer, `y=b^m`.  
It would return an error if `y` is not a power of `b`.  
Right now, using the log is not ideal since

```julia
julia> log(7,7^5)
5.000000000000001

```

which is not a `Int`.  
I see ways to code a function `f(b,y)` doing that, I just wondered if there were a dedicated function already doing that.

---

<div class="post-metadata">

### Author: ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)
#### Post date: [November 4, 2022, 2:21pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/2 "2022-11-04T14:21:01Z")

</div>

If you know that the result for your arguments ought to be an integer, just define an integer log function like this

```julia
julia> logi = Int∘round∘log
Int64 ∘ round ∘ log

julia> logi(7,7^5)
5

```

or for better type safety:

```julia
julia> logi(b::Int, y::Int) = Int(round(log(b,y)))
logi (generic function with 1 method)

julia> logi(3.5,100.0)
ERROR: MethodError: no method matching logi(::Float64, ::Float64)
Stacktrace:
 [1] top-level scope
   @ REPL[3]:1

julia> logi(7,7^5)
5

```

You could even do type piracy if it’s for your own use only:

```julia
julia> Base.log(b::Int, y::Int) = Int(round(log(Float64(b),Float64(y))))

julia> log(7,7^5)
5

```

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [November 4, 2022, 2:22pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/3 "2022-11-04T14:22:43Z")

</div>

imo we should have this in base because it’s easy to implement badly and hard to do well.

---

<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 4, 2022, 2:27pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/4 "2022-11-04T14:27:07Z")

</div>

> [@Oscar\_Smith](#):
>
> it’s easy to implement badly

Does the Float as an intermediate is the best strategy for performance? ps: Maybe a `logi` function in base doing that should throw an error if the result is not exactly representable by an integer.

ps: @Jeff_Emanuel, why not

```julia
logi(x::Int,y::Int) = round(Int, log(x,y))

```

?  
Just taste, or is there any other reason behind?

---

<div class="post-metadata">

### Author: ![dmetivie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmetivie/32/6926_2.png) [@dmetivie](https://discourse.julialang.org/u/dmetivie)
#### Post date: [November 4, 2022, 2:39pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/5 "2022-11-04T14:39:18Z")

</div>

> [@Jeff\_Emanuel](#):
>
> or for better type safety:
> 
> ```julia
> julia> logi(b::Int, y::Int) = Int(round(log(b,y)))
> logi (generic function with 1 method)
> 
> ```

Now the problem is that

```julia
julia> logi(7,8^5)
5

```

where i would expect an error.

> [@Oscar\_Smith](#):
>
> imo we should have this in base because it’s easy to implement badly and hard to do well.

I share this feeling

---

<div class="post-metadata">

### Author: ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)
#### Post date: [November 4, 2022, 2:39pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/6 "2022-11-04T14:39:37Z")

</div>

No particular reason. It’s just more natural for me as `Int(round(...` rather than `round(Int,...`.

---

<div class="post-metadata">

### Author: ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)
#### Post date: [November 4, 2022, 2:42pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/7 "2022-11-04T14:42:53Z")

</div>

Certainly. I thought from your description that in your use case you knew that the second argument was an integral power of your base, thus the overly simplistic suggestion.

---

<div class="post-metadata">

### Author: ![dmetivie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dmetivie/32/6926_2.png) [@dmetivie](https://discourse.julialang.org/u/dmetivie)
#### Post date: [November 4, 2022, 3:00pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/8 "2022-11-04T15:00:42Z")

</div>

I want to both compute `m` and check that it is an integer.  
If `log(b,y)` was _exact_ it would return exactly `m` when `y = b^m` so I would just do `m = Int(log(b,y))`.  
However, it seems that in some case this do not work e.g. `m = Int(log(b,7,7^5))`.

---

<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 4, 2022, 3:15pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/9 "2022-11-04T15:15:58Z")

</div>

That is trickier than it seems.

For instance:

```julia
julia> convert(Int, log(7,7^5))
ERROR: InexactError: Int64(5.000000000000001)

```

Thus, the floating point `log` breaks the representability of the result as an Integer.

The function should probably be something on the lines of:

```julia
julia> function logi(x::Int,y::Int)
           x == 0 && error()
           i = 0
           r = x
           while abs(r) < abs(y)
               i += 1
               r *= x
           end
           r == y ? i+1 : error()
       end
logi (generic function with 2 methods)

julia> logi(-7,(-7)^5)
5

julia> logi(7,(7)^5)
5

```

but written more carefully, because that one fails in a series of cases, for instance:

```julia
julia> logi(-1,1)
ERROR:

```

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [November 4, 2022, 3:35pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/10 "2022-11-04T15:35:45Z")

</div>

I would definitely like a `floorlog`/`ceillog` function. Note that elements of these hypothetical functions already exist in the implementations of `prevpow`/`nextpow`.

~~Or maybe these are implemented as `RoundingMode` arguments to `Base.log`? But that might be piling too much disparate functionality under one function.~~

---

<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 4, 2022, 4:31pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/12 "2022-11-04T16:31:13Z")

</div>

> [@dmetivie](#):
>
> I want to both compute `m` and check that it is an integer.

```julia
julia> function logi(b::Int, y::Int)                                                                                                                                    
           n = round(Int, log(b, y))                                                                                                                                     
           b^n == y || throw(ArgumentError("$y is not a power of $b"))                                                                                                  
           return n                                                                                                                                                     
       end
logi (generic function with 1 method)

julia> using BenchmarkTools

julia> b = 5; y = 5^12;

julia> @btime logi($b, $y)
  32.060 ns (0 allocations: 0 bytes)
12

```

For comparison:

```julia
julia> @btime log($b, $y)
  35.000 ns (0 allocations: 0 bytes)
12.000000000000002

```

Edit: Perhaps someone could explain why `logi` is slightly but consistently faster than `log` with the same inputs.

---

<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 4, 2022, 5:31pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/13 "2022-11-04T17:31:35Z")

</div>

> [@Oscar\_Smith](#):
>
> imo we should have this in base because it’s easy to implement badly and hard to do well.

Isn’t this a hard problem to solve exactly in general, i.e. the [discrete logarithm problem](https://en.wikipedia.org/wiki/Discrete_logarithm) if you want to support `BigInt`? I guess it only becomes hard if there is a `mod` operation?

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [November 4, 2022, 8:19pm UTC](https://discourse.julialang.org/t/is-there-a-dedicated-function-computing-m-int-log-b-b-m/89776/14 "2022-11-04T20:19:20Z")

</div>

Yeah. It’s only hard with a modulo. Without, there is a simple algorithm that’s `O(log(n))` steps that just repeatedly squares until you pass the number and than does a binary search to find the true answer.
