Forum Webscript.Ru

Программирование => PHP => Тема начата: Orme от 25 Января 2007, 19:15:53

Название: pow() и bcpow() не катят
Отправлено: Orme от 25 Января 2007, 19:15:53
Нужна функция или алгоритм, возводящие число в степень.

Возвращаемое значение и передаваемые аргументы могут быть очень большими,
поэтому pow() не подходит.
bcpow() тоже не подходит, потому что в качестве аргументов принимает
только натуральные числа, а нужно, чтобы принимала любые положительные,
в том числе и дробные, и меньше 1.
//
строка большое_число mypow ( строка большое_число, строка степень_любое_полож_число )

Может, кто-нибудь сталкивался с аналогичной проблемой, и может помочь?

-----
Да, gmp_pow() воспользоваться не могу, потому что работаю под win32.
    И может с ней аналогичная ситуация.
Название: pow() и bcpow() не катят
Отправлено: andymc от 26 Января 2007, 13:33:09
Orme
Объясни, почему pow() не подходит?
Большое число - насколько большое: 1000, миллион, миллиард?
Название: pow() и bcpow() не катят
Отправлено: CGVictor от 26 Января 2007, 13:42:20
[off]andymc
Максимальный вывод у pow - 2^31.[/off]
Название: pow() и bcpow() не катят
Отправлено: andymc от 27 Января 2007, 11:16:19
CGVictor, Orme
[OFF]Эксперимент показал, что максимальная степень по базе \'2\' - это 39 (pow(2,39))
pow(2,39) = 549 755 813 888
pow(2,40) = 1.099 511 627 78E+012
Дальше идёт округление
Функци bcpow() действительно не считает дробные степени.[/OFF]

Пусть m - степень (дробная). например, 25,86
Тогда m1 = floor(m); // целая часть 25
m2 = m - m1; // дробная часть 0,86
Теперь, согласно форумуле
bcpow(a, m) = bcpow(a, m1) * pow(a, m2);

Готовая функция может выглядеть так:
function mypow($x, $y, $scale = 0){
if (is_float($y)){
$y1 = floor($y);
$y2 = $y - $y1;
return bcmul(bcpow($x, $y1), pow($x, $y2), $scale);
} else {
return bcpow($x, $y);
}
}
Название: pow() и bcpow() не катят
Отправлено: Orme от 28 Января 2007, 00:55:00
andymc
Цитировать
bcpow(a, m) = bcpow(a, m1) * pow(a, m2)


Откуда формула?
Название: pow() и bcpow() не катят
Отправлено: Orme от 28 Января 2007, 01:00:36
andymc
Цитировать
function mypow($x, $y, $scale = 0){
    if (is_float($y)){
        $y1 = floor($y);
        $y2 = $y - $y1;
        return bcmul(bcpow($x, $y1), pow($x, $y2), $scale);
    } else {
        return bcpow($x, $y);
    }
}


Не будет работать. Нужна формула (ln(a) * a^X)*x + a^X.
В ней тоже много проблем, которые стандартными способами не решишь.
Название: pow() и bcpow() не катят
Отправлено: andymc от 28 Января 2007, 01:24:16
Я сам проверял, работает нормально
Цитировать
bcpow(a, m) = bcpow(a, m1) * pow(a, m2)
это формула школьного курса, переделанная под php (\'a\' в степени \'c\'+\'b\' = \'a\' в степени \'c\' умножить на \'a\' в степени \'b\')
Логически елси подумать, это должно работать
Название: pow() и bcpow() не катят
Отправлено: Orme от 30 Января 2007, 22:06:21
m2 - все равно дробь. Смысл какой?

Нужно привести в итоге к целочисленным вычислениям.

Тут надо переводить decimal в fraction (типа 1/2, 5/4)

Далее по формуле a^m/n = n-ный корень из a^m
Название: pow() и bcpow() не катят
Отправлено: andymc от 30 Января 2007, 22:42:36
m2 - дробь, но pow() же работает с дробями. Смысл в том, чтобы разделить задачу на 2 части: отдельно считать целое и дробное.
Цитировать
переводить decimal в fraction (типа 1/2, 5/4)
что-то мне кажется, что это невозможно
Цитировать
a^m/n = n-ный корень из a^m
я сначала тоже так думал, только вот n-ный корень ты не сможешь точно подсчитать:
pow() ограничена
bcpow() не работает с дробями

ты функцию проверял? Она работает?
Название: pow() и bcpow() не катят
Отправлено: Orme от 01 Февраля 2007, 08:24:11
Цитировать
что-то мне кажется, что это невозможно


- очень даже несложная функция:


function dec2frac($decimal) {

$decimal = (string)$decimal;
$num = "";
$den = "1";
$dec = false;

for ($i = 0, $len = strlen($decimal); $i < $len; $i++) {
if ($dec) $den = gmp_mul($den, "10");
if ($decimal{$i} == ".") {
$dec = true;
}else{
$num .= $decimal{$i};
}
}

if($den == "1") return $num;

if (strpos($num, "0") === 0) $num = ltrim($num, "0");

$gcd = gmp_gcd($num, $den);

$num = gmp_strval(gmp_div($num, $gcd));
$den = gmp_strval(gmp_div($den, $gcd));

return $num."/".$den;

}
Название: pow() и bcpow() не катят
Отправлено: Orme от 01 Февраля 2007, 08:25:42
Да, только здесь gmp используется. Забыл сказать.
Но, в принципе, можно и без нее обойтись.
Название: pow() и bcpow() не катят
Отправлено: andymc от 01 Февраля 2007, 13:36:58
спасибо, что расказал про GMP.