在 PHP 中处理大量数据

发布于 2024-07-07 15:07:20 字数 513 浏览 11 评论 0 原文

按照使用 模幂 .wikipedia.org/wiki/Fermat_primality_test" rel="noreferrer">费马素性测试 对于大数(100,000+),它需要一些非常大的计算。

当我将两个大数相乘(例如:62574 和 62574)时,PHP 似乎将结果转换为浮点数。 获取其模值会返回奇怪的值。

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

有什么方法可以让PHP正确执行这些计算吗? 或者,是否有另一种方法来查找适用于大数的模值?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

为人所爱 2024-07-14 15:07:20

由于某种原因,PHP 中有两个标准库处理任意长度/精度数字: BC 数学GMP。 我个人更喜欢GMP,因为它更新鲜,API更丰富。

基于 GMP,我实现了 Decimal2 class 来存储和处理货币金额(例如 100.25 美元) )。 大量的 mod 计算没有任何问题。 使用非常大的数字进行测试。

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.

错々过的事 2024-07-14 15:07:20

用这个

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

use this

 $num1 = "123456789012345678901234567890";
 $num2 = "9876543210";
 $r    = mysql_query("Select @sum:=$num1 + $num2");
 $sumR = mysql_fetch_row($r);
 $sum  = $sumR[0];
寄居人 2024-07-14 15:07:20

您看过 bcmod() 吗? php 在 32 位平台上存在超过 2^31 - 1 的整数问题。

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

have you taken a look at bcmod()? php has issues with integers over 2^31 - 1 on 32 bit platforms.

var_dump(bcmod("$x", '104659') ); // string(4) "2968"
行至春深 2024-07-14 15:07:20

我建议您尝试 BigInteger。 如果这不起作用,您可以使用 SWIG 添加用于大整数计算的 C/C++ 代码并将其链接到您的代码中。

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.

锦欢 2024-07-14 15:07:20

我为您编写了一个非常小的代码,它肯定可以在大数字的情况下工作 -

<?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 手册中查看一些好的 GMP 函数 -
http://php.net/manual/en/ref.gmp.php

I wrote a very small code for you that will surely work in case of big numbers-

<?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
    */
?>

You simply have to use strings for storing big numbers and to operate on them use GMP functions in PHP.

You may check some good GMP functions in the official PHP manual here-
http://php.net/manual/en/ref.gmp.php

寻找一个思念的角度 2024-07-14 15:07:20

我找到了另一个解决方案,但数字将存储为字符串。 一旦将其转换回数字,您将受到底层平台精度的限制。 在 32 位平台上,可以表示为 int 类型的最大 int 是 2,147,483,647:

/**
 * @param string $a
 * @param string $b
 * @return string
 */
function terminal_add($a,$b)
{
    exec('echo "'.$a.'+'.$b.'"|bc',$result);
    $ret = "";
    foreach($result as $line) $ret .= str_replace("\\","",$line);
    return $ret;
}

// terminal_add("123456789012345678901234567890", "9876543210")
// output: "123456789012345678911111111100"

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)
{
    exec('echo "'.$a.'+'.$b.'"|bc',$result);
    $ret = "";
    foreach($result as $line) $ret .= str_replace("\\","",$line);
    return $ret;
}

// terminal_add("123456789012345678901234567890", "9876543210")
// output: "123456789012345678911111111100"
梦冥 2024-07-14 15:07:20
$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);
$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);
溺渁∝ 2024-07-14 15:07:20
<?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);
?>
<?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);
?>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文