# I think one can calculate logarithmn using only one known logarithmn value log2(1.5)

**URL:** <https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213>\
**Category:** Offtopic\
**Created:** [September 9, 2024, 10:02am UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213 "2024-09-09T10:02:11Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [September 9, 2024, 10:02am UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/1 "2024-09-09T10:02:11Z")

</div>

If civilization collapses , then how do we calculate logarithm. I think that one can calculate logarithmn using only one knwn logarithm value log2(1.5).

I already know that log10(x) = ln(x)/ln(10)

So if we know log of any base, then we can calculate log10 of any number.

Therefore we should look for a base that is the easiest to calculate and the base is 2. I do wish to calculate the log of base 1 but I leave that puzzle to another day.

Then we have

logB( x + y) = logB(x) + logB(1 + y/x)

so

log2(1.75) = log2(1.5 + 0.25) = log2(1.5) + log2(1 + 0.25/1.5)

= log2(1.5) + log2(1) + log2(1 + (0.25/1.5)/1)

= log2(1.5) + log2(1) + log2(1 + 0.166666666)

= log2(1.5) + log2(1) + log2(1) + log2(1.1666666)

= log2(1.5) + log2(1) + log2(1) + log2(2.333333 / 2 )

= log2(1.5) + log2(1) + log2(1) + log2(2.333333) + log2(1/2)

so all we need is to calculate log2(2.3333333) and we have the answer (since we know log2(1.5)

log2(2.333333) = log2(1.5 + 0.83333333)

and we use the identity ( x = 1.5 )

logB( x + y) = logB(x) + logB(1 + y/x) Again!!!

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [September 9, 2024, 1:38pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/2 "2024-09-09T13:38:36Z")

</div>

> [@StevenSiew](#):
>
> If civilization collapses , then how do we calculate logarithm.

Mathematics will be rediscovered (or just not forgotten), and we can use the same approaches we used to, via iterative methods. See for example, [this section](https://en.wikipedia.org/wiki/Logarithm#Calculation) of the Wikipedia page on logarithms.

> [@StevenSiew](#):
>
> I do wish to calculate the log of base 1 but I leave that puzzle to another day.

(I’m not sure if this is intended as a joke, but if not, let me point out that the base-1 logarithm does not make sense. For e.g. \log\_1(2), you’d need to find a real number x such that 1^x = 2, which obviously does not exist (mathematically speaking, f: \mathbb{R}^+ \to \mathbb{R}^+: t \mapsto 1^t (=1) is not surjective). Also, what would be \log\_1(1)? There are many options (f is not injective either).)

> [@StevenSiew](#):
>
> so all we need is to calculate log2(2.3333333)

So to calculate \log\_2(1.75), given knowledge of \log\_2(1.5), you only need to be able to calculate \log\_2(7/3). But how did this simplify the problem? Also, what makes 1.5 special here? You could equally use any other positive number.

It’s possible that there’s some merit to your approach, if you can show that you are indeed simplifying the problem / obtaining a partial solution (e.g. digits in the binary or decimal expansion). If so, you’ll have (re)discovered an iterative method to calculate logarithms, like the ones linked to above.

---

<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:** [September 9, 2024, 1:39pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/3 "2024-09-09T13:39:22Z")

</div>

Note that you can also use Taylor series and reductions to bring the number close to 1.

---

<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:** [September 9, 2024, 2:03pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/4 "2024-09-09T14:03:11Z")

</div>

> [@StevenSiew](#):
>
> If civilization collapses , then how do we calculate logarithm.

Future archeologists will unearth some slide rules made of stainless steel. Like this rare beautiful _circular_ slide rule from Hungary:

 ![](https://global.discourse-cdn.com/julialang/original/3X/2/d/2daf1fa631d1ea25edfd960e694a76b25cc16ce1.jpeg)  
(image courtesy of the [Slide Rule Museum](https://sliderulemuseum.org/), apologies to nerds like me who will end up wasting hours looking at them).

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [September 9, 2024, 3:12pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/5 "2024-09-09T15:12:56Z")

</div>

The proof of the pudding is in the eating.

```julia
maxiter = 64

function mylog2(level::Int64,x::Float64)
    global maxiter
    if level > maxiter
        return 0.0
    end
    level += 1 # Increase the depth of function call
    local adjustment::Int64=0
    while x >= 3.0
        adjustment += 1
        x /= 2.0
    end
    while x < 1.5
        adjustment -= 1
        x *= 2.0
    end
    # at this point the value of x >= 1.5 and x < 3.0
    if x == 1.5 # do the case when x is exactly 1.5
        return Float64(adjustment) + log(2,1.5)
    end
    # at this point x > 1.5
    # logB( x + y) = logB(x) + logB(1 + y/x)
    # log2( 1.5 + d) = log2(1.5) + log2(1 + d/1.5)
    # = log2(1.5) + log2(1) + log2(1 + (d/1.5)/1)
    # = log2(1.5) + log2(1 + d/1.5)
    #
    # let z = 1 + d/1.5
    # if z >= 1.5
    # = log2(1.5) + mylog2(level,z)
    # otherwise
    # = log2(1.5) + 0.5 * mylog2(level,z^2)
    #
    local d,z
    d = x - 1.5
    z = 1 + d/1.5
    if z >= 1.5
        return Float64(adjustment) + log(2,1.5) + mylog2(level,z)
    else
        return Float64(adjustment) + log(2,1.5) + 0.5 * mylog2(level,z*z)
    end
end

println("log2(4.5) = ",log(2,4.5) )
println("mylog2(0,4.5) = ",mylog2(0,4.5) )

# Sample output
#
# log2(4.5) = 2.1699250014423126
# mylog2(0,4.5) = 2.169925001442312

```

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [September 9, 2024, 3:18pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/6 "2024-09-09T15:18:14Z")

</div>

And this is the magic number log2(1.5)

julia\> log(2,1.5)  
0.5849625007211562

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [September 9, 2024, 4:07pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/7 "2024-09-09T16:07:10Z")

</div>

That indeed seems to work. Note that there is nothing special about `1.5`: if you replace it with any other number x \> 0 the approach is still valid. In particular, if you take x = 1, you don’t need to protect the value of \log\_2(1.5) during the apocalypse, as you now simply have \log\_2(x) = 0. This further makes the algorithm a bit easier, as z = x and you will always take the `else` branch.  
In fact, with x = 1 you’ll have rediscovered the iterative approach described [here](https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation).

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [September 9, 2024, 7:52pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/8 "2024-09-09T19:52:58Z")

</div>

The book by Briggs, Arithmetica Logarithmica (1624), had a large part with methods for calculating logarithms.

> **[Arithmetica Logarithimica : Briggs, Henry : Free Download, Borrow, and...](https://archive.org/details/arithmeticalogar00brig/page/n5/mode/2up)**

---

<div class="post-metadata">

**Author:** ![TimG](https://avatars.discourse-cdn.com/v4/letter/t/82dd89/32.png) [@TimG](https://discourse.julialang.org/u/TimG)\
**Post date:** [September 9, 2024, 10:53pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/9 "2024-09-09T22:53:26Z")

</div>

I had one of these circular slide rules but, alas, only a plastic one. I fear it will no longer be useful to future archaeologists!

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [September 10, 2024, 7:03am UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/10 "2024-09-10T07:03:39Z")

</div>

Here is the version 2 of the source code. Yes, changing the konst from 1.5 to 1.4 works. It works as long as konst is greater than 1.0

it even works when konst is 2.0 which means that is nothing special about log2(1.5)

```julia
const maxiter = 64
const konst = 1.5

function mylog2(level::Int64,x::Float64)
    global maxiter
    global konst
    if level > maxiter
        return 0.0
    end
    level += 1 # Increase the depth of function call
    local adjustment=0.0
    while x >= 2*konst
        adjustment += 1.0
        x /= 2.0
    end
    while x < konst
        adjustment -= 1.0
        x *= 2.0
    end
    # at this point the value of x >= 1.5 and x < 3.0
    if x == konst # do the case when x is exactly 1.5
        return adjustment + log(2,konst)
    end
    # at this point x > 1.5
    # logB( x + y) = logB(x) + logB(1 + y/x)
    # log2( 1.5 + d) = log2(1.5) + log2(1 + d/1.5)
    # = log2(1.5) + log2(1) + log2(1 + (d/1.5)/1)
    # = log2(1.5) + log2(1 + d/1.5)
    #
    # let z = 1 + d/1.5
    # if z >= 1.5
    # = log2(1.5) + mylog2(level,z)
    # otherwise
    # = log2(1.5) + 0.5 * mylog2(level,z*z)
    #
    local d,z
    d = x - konst
    z = 1 + d/konst
    if z >= konst
        return adjustment + log(2,konst) + mylog2(level,z)
    else
        local numofsquaring = 0
        local newz = z
        while newz < konst
            newz = newz*newz
            numofsquaring += 1
        end
        return adjustment + log(2,konst) + 0.5^numofsquaring * mylog2(level,newz)
    end
end

mylog2(x) = mylog2(0,x) # stub to have single arguement

println("log2(4.5) = ",log(2,4.5) )
println("mylog2(0,4.5) = ",mylog2(4.5) )

# Sample output
#
# log2(4.5) = 2.1699250014423126
# mylog2(0,4.5) = 2.169925001442312

```

---

<div class="post-metadata">

**Author:** ![photor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/photor/32/14343_2.png) [@photor](https://discourse.julialang.org/u/photor)\
**Post date:** [September 10, 2024, 12:41pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/11 "2024-09-10T12:41:00Z")

</div>

what is the optimal value of your konst? 😅

---

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [September 10, 2024, 1:37pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/12 "2024-09-10T13:37:52Z")

</div>

Hi,

I think you are abusing and overusing `global` and `local`, it’s not very Julia idiomatic style.

This results in the same:

```julia
function _mylog2(level::Integer, x; maxiter=64, konst=1.5)
    if level > maxiter
        return 0.0 
    end 
    level += 1 # Increase the depth of function call
    adjustment=0.0

    while x >= 2*konst
        adjustment += 1.0 
        x /= 2.0 
    end 

    while x < konst
        adjustment -= 1.0 
        x *= 2.0 
    end 
    if x == konst # do the case when x is exactly 1.5
        return adjustment + log(2,konst)
    end 
    d = x - konst
    z = 1 + d / konst

    if z >= konst
        return adjustment + log(2,konst) + _mylog2(level,z)
    else
        numofsquaring = 0 
        newz = z 
        while newz < konst
            newz = newz*newz
            numofsquaring += 1
        end
        return adjustment + log(2,konst) + 0.5^numofsquaring * _mylog2(level,newz)
    end 
end

```

There is more ways to improve such as being generic to the input type `T`. and avoiding explicit values such as `2.0` which introduces conversions to `Float64`.

---

<div class="post-metadata">

**Author:** ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)\
**Post date:** [September 10, 2024, 1:45pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/13 "2024-09-10T13:45:22Z")

</div>

Here’s how they do it professionally:

> <https://github.com/JuliaLang/julia/blob/master/base/special/log.jl>

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [September 11, 2024, 8:31am UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/14 "2024-09-11T08:31:07Z")

</div>

Here is version 3 of the source code which can handle different Floating Point Types.

```julia
using DoubleFloats

function mylog2(level::Integer,x;maxiter=64,konst=1.5)
    local mytype = typeof(x)
    local myone = one(mytype)
    local mytwo = myone + myone
    local mykonst = convert(mytype,konst)
    if level > maxiter
        return zero(mytype)
    end
    level += 1 # Increase the depth of function call
    local adjustment = zero(mytype)
    while x >= 2*mykonst
        adjustment += myone
        x /= mytwo
    end
    while x < mykonst
        adjustment -= myone
        x *= mytwo
    end
    # at this point the value of x >= 1.5 and x < 3.0
    if x == mykonst # do the case when x is exactly 1.5
        return adjustment + log(2,mykonst)
    end
    # at this point x > 1.5
    local d,z
    d = x - mykonst
    z = myone + d/mykonst
    if z >= convert(mytype,mykonst)
        return adjustment + log(2,mykonst) + mylog2(level,z,maxiter=maxiter,konst=konst)
    else
        local numofsquaring = 0
        local newz = z
        while newz < mykonst
            newz = newz*newz
            numofsquaring += 1
        end
        return adjustment + log(2,mykonst) + (myone/mytwo)^numofsquaring * mylog2(level,newz,maxiter=maxiter,konst=konst)
    end
end

mylog2(x) = mylog2(0,x) # stub to have single arguement

println("log2(4.5) = ",log(2,4.5) )
println("mylog2(0,4.5) = ",mylog2(4.5) )
println()
println("log2(4.5) = ",log(2,big(4.5)) )
println("mylog2(0,4.5) = ",mylog2(DoubleFloat(4.5)) )
println("mylog2(0,4.5) = ",mylog2(big(4.5)) )
# Sample output
#
# log2(4.5) = 2.1699250014423126
# mylog2(0,4.5) = 2.169925001442312

```

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [September 11, 2024, 8:47am UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/15 "2024-09-11T08:47:06Z")

</div>

“what is the optimal value of your konst?”

The optimum value of konst is 2

We have to remember log2(2) == 1

---

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [September 11, 2024, 9:24am UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/16 "2024-09-11T09:24:16Z")

</div>

Here without `local` (it is not required):

```julia
function mylog2(level::Integer, x::T;maxiter=64,konst=T(1.5)) where T
    if level > maxiter
        return zero(T)
    end 
    level += 1 # Increase the depth of function call
    adjustment = zero(T)
    while x >= 2*konst
        adjustment += T(1)
        x /= T(2)
    end 
    while x < konst
        adjustment -= T(1)
        x *= T(2)
    end 
    # at this point the value of x >= 1.5 and x < 3.0
    if x == konst # do the case when x is exactly 1.5
        return adjustment + log(2,konst)
    end 
    # at this point x > 1.5
    d = x - konst
    z = T(1) + d/konst
    if z >= convert(T, konst)
        return adjustment + log(2,konst) + mylog2(level,z,maxiter=maxiter,konst=konst)
    else
        numofsquaring = 0 
        newz = z 
        while newz < konst
            newz = newz*newz
            numofsquaring += 1
        end
        return adjustment + log(2,konst) + (T(1)/T(2))^numofsquaring * mylog2(level,newz,maxiter=maxiter,konst=konst)
    end 
end

```

---

<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:** [September 12, 2024, 12:42pm UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/17 "2024-09-12T12:42:00Z")

</div>

> [@TimG](#):
>
> alas, only a plastic one. I fear it will no longer be useful to future archaeologists!

Would not bet on that, some plastics last for a really long time, unfortunately.

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [September 13, 2024, 3:59am UTC](https://discourse.julialang.org/t/i-think-one-can-calculate-logarithmn-using-only-one-known-logarithmn-value-log2-1-5/119213/18 "2024-09-13T03:59:29Z")

</div>

Thanks for informing me that I can use T where T and I don’t need the local variables.

Here is version 4 of the source code

```julia
using DoubleFloats

function mylog2(level::Integer,x::T;maxiter=64,konst=T(1.5)) where T
    # Sanity Checking x and konst must have the same type
    if typeof(konst) != T 
        println("Failed Sanity Checking. x and konst must have the same type.")
        return NaN
    end
    if level > maxiter
        return zero(T)
    end
    level += 1 # Increase the depth of function call
    adjustment = zero(T)
    while x >= 2*konst
        adjustment += one(T)
        x /= T(2)
    end
    while x < konst
        adjustment -= one(T)
        x *= T(2)
    end
    # at this point the value of x >= 1.5 and x < 3.0
    if x == konst # do the case when x is exactly 1.5
        return adjustment + log(2,konst)
    end
    # at this point x > 1.5
    local d,z
    d = x - konst
    z = one(T) + d/konst
    if z >= konst
        return adjustment + log(2,konst) + mylog2(level,z,maxiter=maxiter,konst=konst)
    else
        local numofsquaring = 0
        local newz = z
        while newz < konst
            newz = newz*newz
            numofsquaring += 1
        end
        return adjustment + log(2,konst) + T(0.5)^numofsquaring * mylog2(level,newz,maxiter=maxiter,konst=konst)
    end
end

mylog2(x) = mylog2(0,x) # stub to have single arguement

println("log2(4.5) = ",log(2,4.5) )
println("mylog2(0,4.5) = ",mylog2(4.5) )
println()
println("log2(4.5) = ",log(2,big(4.5)) )
println("mylog2(0,4.5) = ",mylog2(DoubleFloat(4.5)) )
println("mylog2(0,4.5) = ",mylog2(big(4.5)) )

```

Example:

julia\> mylog2(0,DoubleFloat(4.5),konst=1.2)  
Failed Sanity Checking. x and konst must have the same type.  
NaN

julia\> mylog2(0,DoubleFloat(4.5),konst=DoubleFloat(1.2))  
2.16992500144231236290747788789562852
