如何获得一个非常大的数字(PHP)的log()?

I've looked at php-big numbers, BC Math, and GMP for dealing with very big numbers in php. But none seem to have a function equivilent to php's log(). For example I want to do this:

$result = log($bigNumber, 2);

Would anyone know of an alternate way to get the log base 2 of a arbitray precision point number in php? Maybe Ive missed a function, or library, or formula.

edit: php-bignumbers seems to have a log base 10 function only log10()

One solution combining the suggestions so far would be to use this formula:

log2($num) = log10($num) / log10(2)

in conjunction with php-big numbers since it has a pre-made log10 function.

eg, after installing the php-big numbers library, use:

$log2 = log10($bigNum) / log10(2);

Personally I've decided to use different math/logic so as to not need the log function, and just using bcmath for the big numbers.

In general if you want to implement your high precision log own calculation, I'd suggest 1st use the basic features of logarithm:

log_a(x) = log_b(x) / log_b(a) |=> thus you can recalulate logarith to any base
log(x*y) = log(x) + log(y)
log(a**n) = n*log(a)

where log_a(x) - meaning logarithm to the base a of x; log means natural logarithm

So log(1000000000000000000000.123) = 21*log(1.000000000000000000000123)

and for high precision of log(1+x) use algorithm referenced at http://en.wikipedia.org/wiki/Natural_logarithm#High_precision

One of the great things about base 2 is that counting and shifting become part of the tool set.

So one way to get a 'log2' of a number is to convert it to a binary string and count the bits.

You can accomplish this equivalently by dividing by 2 in a loop. But it seems to me that counting would be more efficient.

gmp_scan0 and gmp_scan1 can be used if you are counting from the right. But you'd have to somehow convert the mixed bits to all ones and zeroes.

But using gmp_strval(num, 2), you can produce a string and do a strpos on it.

if the whole value is being converted, you can do a (strlen - 1) on it.

Obviously this only works when you want an integer log.

I've had a very similar problem just recently.. and so I just scaled the number considerably in order to use the inbuild log to find the fractional part.. (I prefere the log10 for some reason.. don't ask... people are strange, me too) I hope this is selfexplanatory enough.. it returns a float value (since that's what I needed)

function gmp_log($num, $base=10, $full=true)
{
    if($base == 10)
        $string = gmp_strval($num);
    else
        $string = gmp_strval($num,$base);

    $intpart = strlen($string)-1;

    if(!$full)
        return $intpart;

    if($base ==10)
    {
        $string = substr_replace($string, ".", 1, 0);
        $number = floatval($string);
        $lg = $intpart + log10($number);
        return $lg;
    }
    else
    {
        $string = gmp_strval($num);
        $intpart = strlen($string)-1;
        $string = substr_replace($string, ".", 1, 0);
        $number = floatval($string);
        $lg = $intpart + log10($number);

        $lb = $lg / log10($base);
        return $lb;
    }
}

it's quick, it's dirty... but it works well enough to get the log of some RSA sized integers ;)

usage is straight forward as well

$N = gmp_init("11002930366353704069");
echo gmp_log($N,10)."
";
echo gmp_log($N,10, false)."
";
echo gmp_log($N,2)."
";
echo gmp_log($N,16)."
";

returns

19.041508364472 
19 
63.254521604973 
15.813630401243