web-dev-qa-db-ja.com

PHP

Fermat Primality Test を大きな数(100,000+)で使用するときに必要となる モジュラーべき乗 を使用するには、非常に大きな計算が必要です。

2つの大きな数値(例:62574と62574)を乗算すると、PHPは結果をfloatにキャストします。そのモジュラス値を取得すると、奇妙な値が返されます。

$x = 62574 * 62574;
var_dump($x);          // float(3915505476) ... correct
var_dump($x % 104659); // int(-72945)  ... wtf.

PHPこれらの計算を適切に実行する方法はありますか?あるいは、大きな数値で機能するモジュラス値を見つける別の方法がありますか?

52
nickf

何らかの理由で、PHP任意の長さ/精度の数値の処理: BC Math[〜#〜] gmp [〜 #〜] 。私は個人的にはGMPを好みます。

GMPに基づいて、 Decimal2クラス 通貨額(100.25米ドルなど)の保存と処理用に実装しました。 多くのmod計算に問題はありません。 very大きい数でテスト済み。

52
Ivan Krechetov

これを使って

 $num1 = "123456789012345678901234567890";
 $num2 = "9876543210";
 $r    = mysql_query("Select @sum:=$num1 + $num2");
 $sumR = mysql_fetch_row($r);
 $sum  = $sumR[0];
51
K.Sya

bcmod() を見ましたか? phpには、32ビットプラットフォームで2 ^ 31-1を超える整数の問題があります。

var_dump(bcmod("$x", '104659') ); // string(4) "2968"
20
Owen

BigInteger を試すことをお勧めします。それがうまくいかない場合は、 [〜#〜] swig [〜#〜] を使用して、ビッグ整数計算用のC/C++コードを追加し、コードにリンクします。

4
Yuval F

別の解決策を見つけましたが、数値は文字列として保存されます。数値にキャストするとすぐに、基盤となるプラットフォームの精度に制限されます。 32ビットプラットフォームでは、int型として表現できる最大のintは2,147,483,647です。

/**
 * @param string $a
 * @param string $b
 * @return string
 */
function terminal_add($a, $b){
    return Shell_exec('echo "'.$a.'+'.$b.'"|bc');
}

// terminal_add("123456789012345678901234567890", "9876543210")
// output: "123456789012345678911111111100"
3
user2678106
$x = 62574 * 62574;

// Cast to an integer
$asInt = intval($x);
var_dump($asInt);
var_dump($asInt % 104659);

// Use use sprintf to convert to integer (%d), which will casts to string
$asIntStr = sprintf('%d', $x);
var_dump($asIntStr);
var_dump($asIntStr % 104659);
2
bob

あなたのために非常に小さなコードを書きました。

<?php
    $x = gmp_strval(gmp_mul("62574","62574")); // $x="3915505476"
    $mod=gmp_strval(gmp_mod($x,"104659"));  //$mod="2968"

    echo "x : ".$x."<br>";
    echo "mod : ".$mod;

    /* Output:
        x : 3915505476
        mod : 2968
    */
?>

大きな数字を格納するために文字列を使用し、それらを操作するにはPHPのGMP関数を使用する必要があります。

公式のPHPマニュアルをご覧ください http://php.net/manual/en/ref.gmp.php

1
gauravparmar