Работа с большими числами в PHP - PullRequest
51 голосов
/ 17 октября 2008

Чтобы использовать модульное возведение в степень , как вам потребуется при использовании Теста примитивности Ферма с большими числами (100 000+), требуется несколько очень больших вычислений.

Когда я умножаю два больших числа (например, 62574 и 62574), PHP, кажется, приводит результат к плавающему. Получение значения модуля, которое возвращает странные значения.

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

Есть ли способ заставить PHP выполнять эти вычисления правильно? В качестве альтернативы, есть ли другой метод для нахождения значений модуля, который будет работать для больших чисел?

Ответы [ 7 ]

52 голосов
/ 17 октября 2008

По какой-то причине в PHP есть две стандартные библиотеки, обрабатывающие произвольные числа длины / точности: BC Math и GMP . Я лично предпочитаю GMP, так как он более свежий и имеет более богатый API.

На основе GMP я реализовал Десятичный класс2 для хранения и обработки денежных сумм (например, 100,25 долларов США). Множество модовых расчетов без проблем. Протестировано с очень большими числами.

49 голосов
/ 17 мая 2011

используйте это

 $num1 = "123456789012345678901234567890";
 $num2 = "9876543210";
 $r    = mysql_query("Select @sum:=$num1 + $num2");
 $sumR = mysql_fetch_row($r);
 $sum  = $sumR[0];
19 голосов
/ 17 октября 2008

Вы смотрели на bcmod()? У php проблемы с целыми числами свыше 2 ^ 31 - 1 на 32-битных платформах.

var_dump(bcmod("$x", '104659') ); // string(4) "2968"
4 голосов
/ 17 октября 2008

Предлагаю попробовать BigInteger . Если это не сработает, вы можете использовать SWIG , чтобы добавить код C / C ++ для вычисления больших целых чисел и связать его с вашим кодом.

3 голосов
/ 02 февраля 2014

Я нашел другое решение, но число будет сохранено в виде строки. Как только вы приведете его к числовому значению, вы будете ограничены точностью базовой платформы. На 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 голосов
/ 15 сентября 2012
$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);
1 голос
/ 17 мая 2015

Я написал очень маленький код для вас, который наверняка будет работать в случае больших чисел -

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

Вам просто нужно использовать строки для хранения больших чисел, а для работы с ними использовать функции GMP в PHP.

Вы можете проверить некоторые хорошие функции GMP в официальном руководстве PHP здесь- http://php.net/manual/en/ref.gmp.php

...