PHP 日本研討會 2024

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() 設定的預設小數位數,或回退至 bcmath.scale INI 指令的值。

返回值

以字串形式返回結果。

錯誤/例外

在下列情況下,此函式會擲出 ValueError 例外

  • numexponentmodulus 不是格式正確的 BCMath 數值字串
  • numexponentmodulus 具有小數部分
  • exponent 為負值
  • scale 超出有效範圍

如果 modulus0,此函式會擲出 DivisionByZeroError 例外。

變更日誌

版本 描述
8.0.0 scale 現在可為 null。
8.0.0 如果 exponent 為負值,現在會擲出 ValueError 例外,而不是返回 false
8.0.0 除以 0 現在會擲出 DivisionByZeroError 例外,而不是返回 false

範例

以下兩個陳述式在功能上是相同的。然而,bcpowmod() 版本執行時間更短,並且可以接受更大的參數。

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

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

// $a 和 $b 彼此相等。

?>

備註

注意:

由於此方法使用模數運算,非正整數可能會產生意想不到的結果。

參見

  • bcpow() - 將任意精度的數字提高到另一個數字
  • bcmod() - 取得任意精度的數字的模數

新增註解

使用者貢獻的註解 3 個註解

2
ewilde aht bsmdevelopment dawt com
19 年前
PHP 5 之前的版本沒有 bcpowmod。此常式使用 bcdiv、bcmod 和 bcmul 模擬此函式。bcpowmod 非常實用,因為它通常用於實作 RSA 演算法。

函式 bcpowmod(v, e, m) 理應等同於 bcmod(bcpow(v, e), m)。然而,對於 RSA 演算法中用作金鑰的大數字,bcpow 函式會產生一個太大而溢位的數字。對於任何大於數萬的指數,bcpow 都會溢位並傳回 1。

此常式會迴圈執行,針對指數中的每個 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);
}
-3
rrasss at gmail dot com
18 年前
然而,如果您閱讀他的完整註解,您會看到這一段
「函式 bcpowmod(v, e, m) 理應等同於 bcmod(bcpow(v, e), m)。然而,對於 RSA 演算法中用作金鑰的大數字,bcpow 函式會產生一個太大而溢位的數字。對於任何大於數萬的指數,bcpow 都會溢位並傳回 1。」

因此,如果您使用較大的指數,"任何大於數萬的指數",您仍然可以使用他的函式,並且應該這樣做 (而不是使用 bcmod(bcpow(v, e), m) )。
-5
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