Lavorare con grandi numeri in PHP

Utilizzare modulare l’elevamento a potenza come sarebbe necessario quando si utilizza il Fermat Test Di Primalità con grandi numeri (oltre 100.000), chiama per alcune grandi calcoli.

Quando ho moltiplicare due grandi numeri (ad esempio: 62574 e 62574) PHP sembra gettare il risultato di un galleggiante. Ottenere il modulo e il valore che restituisce valori strani.

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

C’è un modo per rendere PHP eseguire questi calcoli correttamente? In alternativa, c’è un altro metodo per la ricerca di valori del modulo che lavorano per i grandi numeri?

  • Nota: come si può vedere ufficiale, manuale PHP, nel commenti, questo perché % utilizza un wrapper per i numeri interi.
  • PHP intero attuazione è fatalmente viziata in quanto 1) è assolutamente dipendente dalla piattaforma (endianess e dimensione in bit) 2) PHP utilizza solo gli interi con segno e 3) andando al di fuori dell’intervallo per un valore integer con segno, fatale la parte che entra in gioco, come sarà il cast risultato di un galleggiante. Il che significa che se si fa 1 + 2147483647 su un sistema a 32 bit, si ottiene un galleggiante, che rende l’imballaggio di dati binari “davvero interessante”
  • Moderno, gli utenti possono trovare che essi possono non riprodurre questo comportamento utilizzando i numeri da la domanda sulle lucido moderno 64 bit – anzi, è probabile trovare che quando si var_dump($x) un int e non un galleggiante. Tuttavia, se si tenta di fare $x = PHP_INT_MAX + 1 invece di $x = 62574 * 62574;, essi saranno in grado di riprodurre il resto della follia con successo.
  • forse PHP Tecnologia è migliorata in quanto è una diversa configurazione PHP, ma il codice funziona bene su repl.it
InformationsquelleAutor nickf | 2008-10-17



7 Replies
  1. 52

    Per qualche motivo, ci sono due librerie standard in PHP manipolazione arbitraria lunghezza/numeri a precisione: BC Matematica e GMP. Io personalmente preferisco GMP, come è più fresco e ha più ricco API.

    Base GMP ho implementato Decimal2 classe per l’archiviazione e l’elaborazione di importi in valuta (come USD 100.25). Un sacco di mod calcoli ci w/o eventuali problemi. Testato con molto grandi numeri.

    • GMP è solo per i numeri interi, mentre BC Matematica è per i numeri a virgola mobile.
    • No, BC Matematica supporta arbitraria precisione di punto fisso. I numeri in virgola mobile sono completamente diversi.
    • Hai assolutamente ragione, sì. Quanto sopra è stato un veloce commento dove volevo semplicemente dire GMP == int && BC == float. 🙂
  2. 49

    utilizzare questo

     $num1 = "123456789012345678901234567890";
     $num2 = "9876543210";
     $r    = mysql_query("Select @sum:=$num1 + $num2");
     $sumR = mysql_fetch_row($r);
     $sum  = $sumR[0];
    • Zomg, che è sia un impressionante e di una brutta risposta.
    • sei serio?
    • Mi dispiace, ma il SQL server è un server SQL, un calcolatore.
    • avete mai ordinato stringhe utilizzando la casella di riepilogo Delphi?
    • Dato Delphi popolarità dubito che qualcuno abbia negli ultimi 10 anni.
    • C’è qualche altro modo per ordinarli? 😉
    • Si prega di controllare Lazzaro di progetto e si sarebbe sorpreso di quanto bene il Pascal comunità oggi 🙂

  3. 19

    hai dato un’occhiata al bcmod()? php ha problemi con i numeri interi oltre 2^31 – 1 su piattaforme a 32 bit.

    var_dump(bcmod("$x", '104659') ); //string(4) "2968"
    • ehm… su piattaforme a 32 bit
    • Che è ancora l’arco di molti NASes nell’anno 2017…
  4. 4

    Ti suggerisco di provare BigInteger. Se questo non funziona, si può utilizzare SORSO per aggiungere codice C/C++ per l’intero grande calcoli e link nel tuo codice.

    • Nizza (sarcasmo)…no documentazione di sorta!
  5. 3

    Ho trovato un’altra soluzione, ma il numero è destinato ad essere archiviato come una stringa. Non appena si gettò indietro a un valore numerico, si sarà limitato alla precisione della piattaforma sottostante. Su una piattaforma a 32 bit, la più grande int si può rappresentare come un tipo 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"
    • Un pò impressionante pensare qui.
  6. 3
    $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);
    • Cosa ne pensi di questo?
    • -1; questa risposta non riesce a capire l’OP problema, figuriamoci risolverlo. Chiamata intval() su un carro che è al di sopra di PHP_INT_MAX darà un selvaggiamente risultato non corretto. L’unico motivo per cui funziona per voi con 62574 * 62574 (il numero della domanda nel 2008) è più moderno PHP che si basa il numero è al di sotto PHP_INT_MAX – ma per lo stesso motivo, la domanda richiedente codice originale funziona bene su sistemi moderni e nessun cambiamento è necessario. Aumentare il numero sei quadratura fino a quando si finisce con $x essere costretti ad un galleggiante, e vi accorgerete che questo è rotto.
    • Il codice mostra la differenza tra l’uso di intval e sprintf-che offre un potenziale di lavoro intorno a via sprintf.
  7. 1

    Ho scritto un piccolo codice per voi che sicuramente lavoro in caso di grandi numeri-

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

    È sufficiente utilizzare le stringhe per la memorizzazione di grandi numeri e di operare su di essi utilizzare GMP funzioni in PHP.

    Si può verificare qualche buon GMP funzioni di ufficiale di PHP manuale qui-
    http://php.net/manual/en/ref.gmp.php

Lascia un commento