PHP Conference Nagoya 2025

bcpowmod

(PHP 5, PHP 7, PHP 8)

bcpowmod Возводит число произвольной точности в степень и возвращает остаток от деления степени числа на абсолютное значение третьего аргумента

Описание

bcpowmod(
    string $num,
    string $exponent,
    string $modulus,
    ?int $scale = null
): string

Функция возводит число num в степень exponent методом быстрого возведения в степень и возвращает остаток от деления степени числа на модуль числа в аргументе modulus.

Список параметров

num

Основание степени в виде строки с целым числом.

exponent

Показатель степени в виде строки с неотрицательным целым числом.

modulus

Модуль в виде строки с целым числом.

scale
Параметр устанавливает количество знаков после десятичного разделителя, которое вернётся в результате. При значении null количество знаков после десятичного разделителя равняется значению по умолчанию, которое установили для параметра глобально функцией bcscale(), или резервному значению, которое указали в INI-директиве bcmath.scale, если глобальное значение не установили.

Возвращаемые значения

Функция возвращает результат в виде строки.

Ошибки

Функция выбрасывает ошибку ValueError в следующих случаях:

  • Значение аргумента num, exponent или modulus оказалось строкой, которую сформировали неправильно с точки зрения допустимого формата числовых строк в модуле BCMath
  • Значение аргумента num, exponent или modulus содержит дробную часть
  • В аргументе exponent передали отрицательное значение
  • Значение аргумента scale выходит за пределы допустимого диапазона

Функция выбрасывает ошибку DivisionByZeroError, если значение аргумента modulus равняется 0

Список изменений

Версия Описание
8.0.0 Параметр scale теперь принимает значение null.
8.0.0 Функция теперь выбрасывает ошибку ValueError вместо возврата значения false, если показатель степени exponent оказался отрицательным значением.
8.0.0 Деление на 0 теперь выбрасывает ошибку DivisionByZeroError вместо возврата значения false.

Примеры

Следующие выражения дают одинаковый результат. Однако функция bcpowmod() работает быстрее и принимает бо́льшие значения аргументов.

<?php

$a
= bcpowmod($x, $y, $mod);

$b = bcmod(bcpow($x, $y), $mod);

// $a == $b

?>

Примечания

Замечание:

Поскольку функция выполняет операцию взятия остатка, отрицательные числа иногда дают неожиданные результаты.

Смотрите также

  • bcpow() - Возводит в степень число произвольной точности
  • bcmod() - Получает остаток от деления чисел произвольной точности

Добавить

Примечания пользователей 3 notes

up
2
ewilde aht bsmdevelopment dawt com
19 years ago
Versions of PHP prior to 5 do not have bcpowmod in their repertoire. This routine simulates this function using bcdiv, bcmod and bcmul. It is useful to have bcpowmod available because it is commonly used to implement the RSA algorithm.

The function bcpowmod(v, e, m) is supposedly equivalent to bcmod(bcpow(v, e), m). However, for the large numbers used as keys in the RSA algorithm, the bcpow function generates a number so big as to overflow it. For any exponent greater than a few tens of thousands, bcpow overflows and returns 1.

This routine will iterate through a loop squaring the result, modulo the modulus, for every one-bit in the exponent. The exponent is shifted right by one bit for each iteration. When it has been reduced to zero, the calculation ends.

This method may be slower than bcpowmod but at least it works.

function PowModSim($Value, $Exponent, $Modulus)
{
// Check if simulation is even necessary.
if (function_exists("bcpowmod"))
return (bcpowmod($Value, $Exponent, $Modulus));

// Loop until the exponent is reduced to zero.
$Result = "1";

while (TRUE)
{
if (bcmod($Exponent, 2) == "1")
$Result = bcmod(bcmul($Result, $Value), $Modulus);

if (($Exponent = bcdiv($Exponent, 2)) == "0") break;

$Value = bcmod(bcmul($Value, $Value), $Modulus);
}

return ($Result);
}
up
-3
rrasss at gmail dot com
18 years ago
However, if you read his full note, you see this paragraph:
"The function bcpowmod(v, e, m) is supposedly equivalent to bcmod(bcpow(v, e), m). However, for the large numbers used as keys in the RSA algorithm, the bcpow function generates a number so big as to overflow it. For any exponent greater than a few tens of thousands, bcpow overflows and returns 1."

So you still can, and should (over bcmod(bcpow(v, e), m) ), use his function if you are using larger exponents, "any exponent greater than a few tens of thousand."
up
-5
laysoft at gmail dot com
17 years ago
I found a better way to emulate bcpowmod on PHP 4, which works with very big numbers too:

function powmod($m,$e,$n) {
if (intval(PHP_VERSION)>4) {
return(bcpowmod($m,$e,$n));
} else {
$r="";
while ($e!="0") {
$t=bcmod($e,"4096");
$r=substr("000000000000".decbin(intval($t)),-12).$r;
$e=bcdiv($e,"4096");
}
$r=preg_replace("!^0+!","",$r);
if ($r=="") $r="0";
$m=bcmod($m,$n);
$erb=strrev($r);
$q="1";
$a[0]=$m;
for ($i=1;$i<strlen($erb);$i++) {
$a[$i]=bcmod(bcmul($a[$i-1],$a[$i-1]),$n);
}
for ($i=0;$i<strlen($erb);$i++) {
if ($erb[$i]=="1") {
$q=bcmod(bcmul($q,$a[$i]),$n);
}
}
return($q);
}
}
To Top