Mohit Gupta
Mohit Gupta

Reputation: 31

How to calculate log16 of a 256 bit Integer in Golang

how to get the log with base 16 for a math/big Int variable.

Any help would be great since I am new to Go and came from Python and C environment

s := "c6d86e5a2cb4bc532361c2d4940f0b1a0138066e25d65c1c530d080b11f8ca24" // Hex value
i := new(big.Int)
i.SetString(s, 16) // hex value to Big Int
// how to get the log with base 16 for a math/big Int variable.

How it works in python

import math 
a = 0xc6d86e5a2cb4bc532361c2d4940f0b1a0138066e25d65c1c530d080b11f8ca24
a>> 89940344608680314083397671686667731393131665861770496634981932531495305005604L
math.log(a)/math.log(16.0)

answer turns out to be 63.908875905794794

Upvotes: 1

Views: 2966

Answers (3)

MBo
MBo

Reputation: 80257

There is specific approach for log16 and hex input without long arithmetics.

To get integer (floored) result, just count hex digits. In this case there are 63 digits, so you have

  FloorLog16 = 63

Now get 8 first digits (more to enhance precision)

  b = 0xc6d86e5a

and get log16

 p = log(b) / log(16) = 7.908875905775919

Use fractional part of this result to make logarithm more exact

fp = p - Floor(p) = 0.908875905775919
log16(0xc6d86e5a2cb4bc532361c2d4940f0b1a0138066e25d65c1c530d080b11f8ca24) = 
      63 + 0.908875905775919 = 63.908875905775919

Note 12 exact digits

Upvotes: 5

Max von Hippel
Max von Hippel

Reputation: 2970

An interesting property of logarithms is that change-of-base is actually pretty easy.

log_b (x) = log_a (x) / log_a (b)

So if you want to get log_16 (x), you could use the Log function and do change of base:

log_e (x) = log_16 (x) / log_16 (e)
log_16 (e) = approximately 0.36067 
=> log_16 (x) = 0.36067 * log_e (x)

So in Go, I think this would be:

li := Log(i) * 0.36067

Edit: When I wrote the answer above I did not realize that Log wouldn't work on a Big Int. Reading the Go Github, it looks like this is a requested feature in the language which has not yet been implemented due to lack of a satisfactorily quick solution. From what I read it looks like the best solution for the moment, if you must use a Big Int, is probably a Taylor Series implementation, which in my opinion would be non-trivial to write. The thread I linked to indicates that one or more such implementations may exist but are not necessarily computationally correct.

Upvotes: 6

chriopp
chriopp

Reputation: 957

First you need to convert the hex string to the correct hex notation by adding "0x" at the beginning. Next write a log16 method, use strconv to get the integer, than float64 for the input of the log method. Caution: this solution does not deal with integer overflow.

package main

import (
    "fmt"
    "math"
    "strconv"
)

func log16(x float64) float64 {
    return math.Log(x)/math.Log(16.0)   
}

func main() {
    s := "c6d86e5a2cb4bc532361c2d4940f0b1a0138066e25d65c1c530d080b11f8ca24"
    s1 := "0x" + s
    h, _ := strconv.ParseInt(s1,0,64)
    fmt.Println(log16(float64(h)))

}

Upvotes: 1

Related Questions