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

此可选参数用于设置结果中小数点后的位数。如果省略,则默认设置为使用 bcscale() 函数全局设置的小数位数,或者如果未设置,则回退到 0

返回值

将结果作为字符串返回,如果 modulus0exponent 为负数,则返回 false

变更日志

版本 说明
8.0.0 scale 现在可以为空。

示例

以下两个语句在功能上是相同的。但是,bcpowmod() 版本执行时间更短,并且可以接受更大的参数。

<?php
$a
= bcpowmod($x, $y, $mod);

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

// $a 和 $b 相等。

?>

注释

注意:

由于此方法使用模数运算,因此非正整数可能会产生意外的结果。

参见

  • bcpow() - 将任意精度数字提升到另一个数字
  • bcmod() - 获取任意精度数字的模数

添加注释

用户贡献的注释 3 个注释

ewilde aht bsmdevelopment dawt com
18 年前
5 之前的 PHP 版本没有 bcpowmod 函数。此例程使用 bcdiv、bcmod 和 bcmul 模拟此函数。能够使用 bcpowmod 很重要,因为它通常用于实现 RSA 算法。

bcpowmod(v, e, m) 函数应该等效于 bcmod(bcpow(v, e), m)。但是,对于 RSA 算法中用作密钥的大数字,bcpow 函数会生成一个太大而溢出的数字。对于任何大于几万的指数,bcpow 都会溢出并返回 1。

此例程将遍历一个循环,对于指数中的每个位,对结果进行平方,并对模数进行取模。在每次迭代中,指数向右移一位。当指数被缩减为零时,计算结束。

此方法可能比 bcpowmod 慢,但至少它可以工作。

function PowModSim($Value, $Exponent, $Modulus)
{
// 检查是否需要模拟。
if (function_exists("bcpowmod"))
return (bcpowmod($Value, $Exponent, $Modulus));

// 循环直到指数被缩减为零。
$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);
}
rrasss at gmail dot com
18 年前
但是,如果您阅读了他的完整注释,您会看到这段话
"bcpowmod(v, e, m) 函数应该等效于 bcmod(bcpow(v, e), m)。但是,对于 RSA 算法中用作密钥的大数字,bcpow 函数会生成一个太大而溢出的数字。对于任何大于几万的指数,bcpow 都会溢出并返回 1."

因此,如果您使用的是更大的指数,“任何大于几万的指数”,您仍然可以并且应该(比 bcmod(bcpow(v, e), m) 更优)使用他的函数。
laysoft at gmail dot com
17 年前
我发现了一种在 PHP 4 上模拟 bcpowmod 的更好方法,它对非常大的数字也有效

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