PHP
BC Math (calculadora binaria)
Buscar..
Introducción
La calculadora binaria se puede utilizar para calcular con números de cualquier tamaño y precisión hasta 2147483647-1 decimales, en formato de cadena. La calculadora binaria es más precisa que el cálculo flotante de PHP.
Sintaxis
- string bcadd (string $ left_operand, string $ right_operand [, int $ scale = 0])
- int bccomp (string $ left_operand, string $ right_operand [, int $ scale = 0])
- string bcdiv (string $ left_operand, string $ right_operand [, int $ scale = 0])
- string bcmod (string $ left_operand, string $ modulus)
- string bcmul (string $ left_operand, string $ right_operand [, int $ scale = 0])
- string bcpowmod (string $ left_operand, string $ right_operand, string $ modulus [, int $ scale = 0])
- bool bcscale (int $ scale)
- string bcsqrt (string $ operand [, int $ scale = 0])
- string bcsub (string $ left_operand, string $ right_operand [, int $ scale = 0])
Parámetros
bcadd | Suma dos números de precisión arbitrarios. |
---|---|
left_operand | El operando izquierdo, como una cuerda. |
right_operand | El operando correcto, como una cuerda. |
scale | Un parámetro opcional para establecer el número de dígitos después del lugar decimal en el resultado. |
bccomp | Compara dos números de precisión arbitrarios. |
left_operand | El operando izquierdo, como una cuerda. |
right_operand | El operando correcto, como una cuerda. |
scale | Un parámetro opcional para establecer el número de dígitos después del lugar decimal que se utilizará en la comparación. |
bcdiv | Divide dos números de precisión arbitrarios. |
left_operand | El operando izquierdo, como una cuerda. |
right_operand | El operando correcto, como una cuerda. |
scale | Un parámetro opcional para establecer el número de dígitos después del lugar decimal en el resultado. |
bcmod | Obtener el módulo de un número de precisión arbitrario. |
left_operand | El operando izquierdo, como una cuerda. |
modulus | El módulo, como una cuerda. |
bcmul | Multiplica dos números de precisión arbitrarios. |
left_operand | El operando izquierdo, como una cuerda. |
right_operand | El operando correcto, como una cuerda. |
scale | Un parámetro opcional para establecer el número de dígitos después del lugar decimal en el resultado. |
bcpow | Elevar un número de precisión arbitrario a otro. |
left_operand | El operando izquierdo, como una cuerda. |
right_operand | El operando correcto, como una cuerda. |
scale | Un parámetro opcional para establecer el número de dígitos después del lugar decimal en el resultado. |
bcpowmod | Elevar un número de precisión arbitrario a otro, reducido por un módulo específico. |
left_operand | El operando izquierdo, como una cuerda. |
right_operand | El operando correcto, como una cuerda. |
modulus | El módulo, como una cuerda. |
scale | Un parámetro opcional para establecer el número de dígitos después del lugar decimal en el resultado. |
Escala | Establecer el parámetro de escala predeterminado para todas las funciones matemáticas bc. |
scale | El factor de escala. |
bcsqrt | Obtener la raíz cuadrada de un número de precisión arbitraria. |
operand | El operando, como una cuerda. |
scale | Un parámetro opcional para establecer el número de dígitos después del lugar decimal en el resultado. |
bcsub | Resta un número de precisión arbitrario de otro. |
left_operand | El operando izquierdo, como una cuerda. |
right_operand | El operando correcto, como una cuerda. |
scale | Un parámetro opcional para establecer el número de dígitos después del lugar decimal en el resultado. |
Observaciones
Para todas las funciones de BC, si el parámetro de scale
no está establecido, el valor predeterminado es 0, lo que hará que todas las operaciones sean operaciones con enteros.
Comparación entre BCMath y operaciones aritméticas flotantes
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"
Uso de bcmath para leer / escribir un binario largo en un sistema de 32 bits
En los sistemas de 32 bits, los enteros mayores que 0x7FFFFFFF
no pueden almacenarse primitivamente, mientras que los enteros entre 0x0000000080000000
y 0x7FFFFFFFFFFFFFFF
pueden almacenarse primitivamente en sistemas de 64 bits pero no en sistemas de 32 bits ( signed long long
). Sin embargo, dado que los sistemas de 64 bits y muchos otros lenguajes admiten el almacenamiento de enteros signed long long
, a veces es necesario almacenar este rango de enteros en el valor exacto. Hay varias formas de hacerlo, como crear una matriz con dos números o convertir el número entero en su forma decimal legible para el hombre. Esto tiene varias ventajas, como la conveniencia de presentar al usuario y la capacidad de manipularlo directamente con bcmath.
Los métodos de pack
/ unpack
se pueden usar para convertir entre bytes binarios y la forma decimal de los números (ambos de tipo string
, pero uno es binario y el otro es ASCII), pero siempre intentarán convertir la cadena ASCII en un formato de 32 bits. int en sistemas de 32 bits. El siguiente fragmento de código proporciona una alternativa:
/** 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;
}