我查看了php-big numbers,BC Math和GMP来处理php中非常大的数字。但似乎没有一个函数与php的log()
等效。例如,我想这样做:
$result = log($bigNumber, 2);
有人知道在php中获取任意精度点数的日志库2的另一种方法吗?也许我错过了一个函数,库或公式。
编辑:php-bignumbers似乎只有一个基数为10的函数log10()
答案 0 :(得分:3)
一般情况下,如果你想实现高精度日志自己的计算,我建议首先使用对数的基本特征:
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)
其中log_a(x) - 表示x的基数a的对数; log表示自然对数
所以log(1000000000000000000000.123) = 21*log(1.000000000000000000000123)
和高精度的log(1 + x) 使用引用的算法 http://en.wikipedia.org/wiki/Natural_logarithm#High_precision
答案 1 :(得分:1)
结合目前建议的一个解决方案是使用这个公式:
log2($num) = log10($num) / log10(2)
与 php-big numbers 一起使用,因为它具有预先制作的log10功能。
例如,在安装php-big数字库之后,请使用:
$log2 = log10($bigNum) / log10(2);
我个人决定使用不同的数学/逻辑,以便不需要日志功能,只需使用bcmath作为大数字。
答案 2 :(得分:1)
基础2的一大优点是计数和移位成为工具集的一部分。
所以一种方法来获得一个' log2'一个数字是将它转换为二进制字符串并计算位数。
您可以通过在循环中除以2来等效地完成此操作。但在我看来,计数会更有效率。
如果从右边开始计数,可以使用gmp_scan0和gmp_scan1。但是你必须以某种方式将混合位转换为全1和0。
但是使用gmp_strval(num,2),你可以生成一个字符串并在其上做一个strpos。
如果要转换整个值,则可以在其上执行(strlen - 1)。
显然,只有在需要整数日志时才会有效。
答案 3 :(得分:0)
我最近有一个非常类似的问题..所以我只是为了使用内置日志找到小数部分而大大缩放了数字..(我出于某种原因优先考虑log10 ..不要#39; t问...人们很奇怪,我也是 我希望这是足够的自我解决方案.. 它返回一个浮点值(因为那是我需要的)
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;
}
}
它很快,很脏......但是它足以获得一些RSA大小的整数日志;)
用法也是直截了当的
$N = gmp_init("11002930366353704069");
echo gmp_log($N,10)."\n";
echo gmp_log($N,10, false)."\n";
echo gmp_log($N,2)."\n";
echo gmp_log($N,16)."\n";
返回
19.041508364472
19
63.254521604973
15.813630401243