PHP
BC Math (Binärer Rechner)
Suche…
Einführung
Mit dem Binärrechner können Zahlen mit beliebiger Größe und Genauigkeit bis zu 2147483647-1 Dezimalzahlen im Stringformat berechnet werden. Der Binärrechner ist genauer als die Floatberechnung von PHP.
Syntax
- Zeichenfolge bcadd (Zeichenfolge $ left_operand, Zeichenfolge $ right_operand [, int $ scale = 0])
- int bccomp (Zeichenfolge $ left_operand, Zeichenfolge $ right_operand [, int $ scale = 0])
- Zeichenfolge bcdiv (Zeichenfolge $ left_operand, Zeichenfolge $ right_operand [, int $ scale = 0])
- Zeichenfolge bcmod (Zeichenfolge $ left_operand, Zeichenfolge $ modulus)
- Zeichenfolge bcmul (Zeichenfolge $ left_operand, Zeichenfolge $ right_operand [, int $ scale = 0])
- Zeichenfolge bcpowmod (Zeichenfolge $ left_operand, Zeichenfolge $ right_operand, Zeichenfolge $ modulus [, int $ scale = 0])
- bool bcscale (int $ scale)
- Zeichenfolge bcsqrt (Zeichenfolge $ operand [, int $ scale = 0])
- Zeichenfolge bcsub (Zeichenfolge $ left_operand, Zeichenfolge $ right_operand [, int $ scale = 0])
Parameter
bcadd | Fügen Sie zwei beliebige Zahlen hinzu. |
---|---|
left_operand | Der linke Operand als String. |
right_operand | Der rechte Operand als String. |
scale | Ein optionaler Parameter, um die Anzahl der Stellen nach der Dezimalstelle im Ergebnis festzulegen. |
bccomp | Vergleichen Sie zwei beliebige Zahlen mit beliebiger Genauigkeit. |
left_operand | Der linke Operand als String. |
right_operand | Der rechte Operand als String. |
scale | Ein optionaler Parameter zum Festlegen der Anzahl der Stellen nach der Dezimalstelle, die im Vergleich verwendet wird. |
bcdiv | Teilen Sie zwei beliebige Zahlen mit beliebiger Genauigkeit. |
left_operand | Der linke Operand als String. |
right_operand | Der rechte Operand als String. |
scale | Ein optionaler Parameter, um die Anzahl der Stellen nach der Dezimalstelle im Ergebnis festzulegen. |
bcmod | Ermitteln Sie den Modul einer beliebigen Zahl. |
left_operand | Der linke Operand als String. |
modulus | Der Modul als eine Zeichenfolge. |
bcmul | Multiplizieren Sie zwei beliebige Zahlen mit beliebiger Genauigkeit. |
left_operand | Der linke Operand als String. |
right_operand | Der rechte Operand als String. |
scale | Ein optionaler Parameter, um die Anzahl der Stellen nach der Dezimalstelle im Ergebnis festzulegen. |
bcpow | Erhöhen Sie eine beliebige Zahl auf eine andere. |
left_operand | Der linke Operand als String. |
right_operand | Der rechte Operand als String. |
scale | Ein optionaler Parameter, um die Anzahl der Stellen nach der Dezimalstelle im Ergebnis festzulegen. |
bcpowmod | Erhöhen Sie eine beliebige Zahl mit beliebiger Genauigkeit, reduziert um einen bestimmten Modul. |
left_operand | Der linke Operand als String. |
right_operand | Der rechte Operand als String. |
modulus | Der Modul als eine Zeichenfolge. |
scale | Ein optionaler Parameter, um die Anzahl der Stellen nach der Dezimalstelle im Ergebnis festzulegen. |
bcscale | Legen Sie den Standard-Skalierungsparameter für alle bc-Mathematikfunktionen fest. |
scale | Der Skalierungsfaktor |
bcsqrt | Holen Sie sich die Quadratwurzel einer beliebigen Zahl. |
operand | Der Operand als String. |
scale | Ein optionaler Parameter, um die Anzahl der Stellen nach der Dezimalstelle im Ergebnis festzulegen. |
bcsub | Subtrahieren Sie eine beliebige Zahl von beliebiger Genauigkeit. |
left_operand | Der linke Operand als String. |
right_operand | Der rechte Operand als String. |
scale | Ein optionaler Parameter, um die Anzahl der Stellen nach der Dezimalstelle im Ergebnis festzulegen. |
Bemerkungen
Wenn der scale
nicht für alle BC-Funktionen festgelegt ist, wird standardmäßig der Wert 0 verwendet, wodurch alle Operationen als Ganzzahloperationen ausgeführt werden.
Vergleich zwischen BCMath- und Float-Arithmetikoperationen
bcadd vs float + float
var_dump('10' + '-9.99'); // float(0.0099999999999998)
var_dump(10 + -9.99); // float(0.0099999999999998)
var_dump(10.00 + -9.99); // float(0.0099999999999998)
var_dump(bcadd('10', '-9.99', 20)); // string(22) "0.01000000000000000000"
bcsub vs float-float
var_dump('10' - '9.99'); // float(0.0099999999999998)
var_dump(10 - 9.99); // float(0.0099999999999998)
var_dump(10.00 - 9.99); // float(0.0099999999999998)
var_dump(bcsub('10', '9.99', 20)); // string(22) "0.01000000000000000000"
bcmul vs int * int
var_dump('5.00' * '2.00'); // float(10)
var_dump(5.00 * 2.00); // float(10)
var_dump(bcmul('5.0', '2', 20)); // string(4) "10.0"
var_dump(bcmul('5.000', '2.00', 20)); // string(8) "10.00000"
var_dump(bcmul('5', '2', 20)); // string(2) "10"
bcmul vs float * float
var_dump('1.6767676767' * '1.6767676767'); // float(2.8115498416259)
var_dump(1.6767676767 * 1.6767676767); // float(2.8115498416259)
var_dump(bcmul('1.6767676767', '1.6767676767', 20)); // string(22) "2.81154984162591572289"
bcdiv vs float / float
var_dump('10' / '3.01'); // float(3.3222591362126)
var_dump(10 / 3.01); // float(3.3222591362126)
var_dump(10.00 / 3.01); // float(3.3222591362126)
var_dump(bcdiv('10', '3.01', 20)); // string(22) "3.32225913621262458471"
Verwenden von bcmath zum Lesen / Schreiben einer binären Länge auf einem 32-Bit-System
Auf 32-Bit-Systemen können Ganzzahlen größer als 0x7FFFFFFF
nicht primitiv gespeichert werden, während Ganzzahlen zwischen 0x0000000080000000
und 0x7FFFFFFFFFFFFFFF
auf 64-Bit-Systemen primitiv gespeichert werden können, jedoch nicht auf 32-Bit-Systemen ( signed long long
0x7FFFFFFFFFFFFFFF
). Da jedoch 64-Bit-Systeme und viele andere Sprachen das Speichern von mit signed long long
Ganzzahlen unterstützen, ist es manchmal erforderlich, diesen Bereich von Ganzzahlen in exakten Werten zu speichern. Es gibt mehrere Möglichkeiten, dies zu tun, z. B. das Erstellen eines Arrays mit zwei Zahlen oder das Konvertieren der Ganzzahl in ihre vom Menschen lesbare dezimale Form. Dies hat mehrere Vorteile, z. B. die bequeme Darstellung für den Benutzer und die Möglichkeit, es direkt mit bcmath zu bearbeiten.
Die pack
/ unpack
Methoden können verwendet werden, um zwischen binären Bytes und Dezimalform der Zahlen zu konvertieren (beide vom Typ string
, einer ist binär und einer ist ASCII), aber sie versuchen immer, den ASCII-String in ein 32-Bit zu konvertieren int auf 32-Bit-Systemen. Das folgende Snippet bietet eine Alternative:
/** Use pack("J") or pack("p") for 64-bit systems */
function writeLong(string $ascii) : string {
if(bccomp($ascii, "0") === -1) { // if $ascii < 0
// 18446744073709551616 is equal to (1 << 64)
// remember to add the quotes, or the number will be parsed as a float literal
$ascii = bcadd($ascii, "18446744073709551616");
}
// "n" is big-endian 16-bit unsigned short. Use "v" for small-endian.
return pack("n", bcmod(bcdiv($ascii, "281474976710656"), "65536")) .
pack("n", bcmod(bcdiv($ascii, "4294967296"), "65536")) .
pack("n", bcdiv($ascii, "65536"), "65536")) .
pack("n", bcmod($ascii, "65536"));
}
function readLong(string $binary) : string {
$result = "0";
$result = bcadd($result, unpack("n", substr($binary, 0, 2)));
$result = bcmul($result, "65536");
$result = bcadd($result, unpack("n", substr($binary, 2, 2)));
$result = bcmul($result, "65536");
$result = bcadd($result, unpack("n", substr($binary, 4, 2)));
$result = bcmul($result, "65536");
$result = bcadd($result, unpack("n", substr($binary, 6, 2)));
// if $binary is a signed long long
// 9223372036854775808 is equal to (1 << 63) (note that this expression actually does not work even on 64-bit systems)
if(bccomp($result, "9223372036854775808") !== -1) { // if $result >= 9223372036854775807
$result = bcsub($result, "18446744073709551616"); // $result -= (1 << 64)
}
return $result;
}