Working with large numbers in PHP

2020-01-22 12:42发布

To use modular exponentiation as you would require when using the Fermat Primality Test with large numbers (100,000+), it calls for some very large calculations.

When I multiply two large numbers (eg: 62574 and 62574) PHP seems to cast the result to a float. Getting the modulus value of that returns strange values.

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

Is there any way to make PHP perform these calculations properly? Alternatively, is there another method for finding modulus values that would work for large numbers?

标签: php bignum
8条回答
Explosion°爆炸
2楼-- · 2020-01-22 12:52
$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);
查看更多
萌系小妹纸
3楼-- · 2020-01-22 12:56

use this

 $num1 = "123456789012345678901234567890";
 $num2 = "9876543210";
 $r    = mysql_query("Select @sum:=$num1 + $num2");
 $sumR = mysql_fetch_row($r);
 $sum  = $sumR[0];
查看更多
放我归山
4楼-- · 2020-01-22 12:57

I found another solution, but the number will be stored as a string. As soon as you cast it back to a numeric, you'll be restricted to the precision of the underlying platform. On a 32 bit platform, the largest int you can represent as an int type is 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"
查看更多
The star\"
5楼-- · 2020-01-22 12:58

For some reason, there are two standard libraries in PHP handling the arbitrary length/precision numbers: BC Math and GMP. I personally prefer GMP, as it's fresher and has richer API.

Based on GMP I've implemented Decimal2 class for storing and processing currency amounts (like USD 100.25). A lot of mod calculations there w/o any problems. Tested with very large numbers.

查看更多
贪生不怕死
6楼-- · 2020-01-22 13:02

I suggest you try BigInteger. If that doesn't work out, you may use SWIG to add C/C++ code for the big integer calculations and link it into your code.

查看更多
别忘想泡老子
7楼-- · 2020-01-22 13:13
<?php
function add($int1,$int2){
    $int1 = str_pad($int1, strlen($int2), '0', STR_PAD_LEFT);
    $int2 = str_pad($int2, strlen($int1), '0', STR_PAD_LEFT);
    $carry = 0;
    $str = "";
    for($i=strlen($int1);$i>0;$i--){
        $var = $int1[$i-1] + $int2[$i-1] + $carry;
        $var = str_pad($var, 2, '0', STR_PAD_LEFT);
        $var = (string) $var;
        $carry = $var[0];
        $str = $str . $var[1];
    }
    $res = strrev($str.$carry);
    echo ltrim($res,"0");
}
add($int1,$int2);
?>
查看更多
登录 后发表回答