Ver índice
Operaciones aritméticas

        Ocultar índice  

   Índice de contenidos
   Instalación en Windows
   Instalación en Ubuntu
   Servidores seguros
   Páginas dinámicas
   Sintaxis básica
   Operaciones
   Arrays
   Formatos de presentación
   Operadores
   Bucles
   Extraer y ord. información
   Funciones
   Ficheros externos
   Imágenes dinámicas
   Gestión de directorios
   Cookies y sesiones
   Clases y objetos
   Ficheros en formato PDF
   Bases de datos MySQL
   PHP y XML
   PDO - Bases SQLite / MySQL
   MySQL a traves de misqli
   Algo de JavaScript y AJAX


Operaciones aritméticas

En páginas anteriores hemos podido ver que PHP permite utilizar un tipo de variables –las numéricas– cuyos valores puedan ser operados de la misma forma que se hace con los números en la vida cotidiana.

Los resultados de las operaciones pueden utilizarse de forma directa o ser recogidos en una nueva variable. Si asignamos a una nueva variable el resultado de una operación el valor contenido en ella no se modifica si cambian posteriormente los de las variables que intervinieron su creación.

Sintaxis de print y echo

Si queremos encadenar en una sola instrucción –echo ó print– el resultado de una operación junto con otras variables (o cadenas) es imprescindible poner entre paréntesis las instrucciones de la operación. Esta norma solo tiene dos excepciones: en caso de que el print solo contenga la propia operación o cuando utilicemos echo y el separador sea una coma.

Operadores aritméticos

Las diferentes operaciones aritméticas se realizan en PHP utilizando la siguiente sintaxis:

$a + $b

Devuelve la suma de los valores númericos contenidos en las variables $a y $b.

$a – $b

Devuelve la diferencia de los valores númericos contenidos en las variables $a y $b.

$a * $b

Devuelve el producto de los valores númericos contenidos en las variables $a y $b.

$a / $b

Devuelve el cociente de los valores númericos contenidos en las variables $a y $b.

(int)($a / $b)

Devuelve el cociente entero de los valores númericos contenidos en las variables $a y $b.

$a % $b

Devuelve el resto de la división entera de los valores númericos contenidos en las variables $a y $b.

Sqrt($a)

Devuelve la raíz cuadrada del valor númerico contenido en la variables $a.

pow($a,$b)

Devuelve el resultado de elevar el valor númericos contenido en la variable $a a la potencia indicada en la variable $b (ab)

pow($a,1/$b)

Devuelve el resultado de elevar el valor númericos contenido en la variable $a a la potencia indicada en la variable 1/$b lo cual no es otra cosa que la raíz de índice $b de $a.

Abs($a);

Devuelve el valor absoluto del valor númerico contenido en la variable $a.

<?php
# definamos dos variables numéricas asignandoles valores
   $a=23; $b=34;
/* hagamos una suma  y escribamos directamente los resultados
   utilizando las instrucciones print y echo
   con todas sus posibles opciones de sintaxis */
print("La suma de $a + $b es: " . $a . "+" . $b . "=" . ($a+$b)."<br>");
print "La suma de $a + $b es: " . $a . "+" . $b . "=" . ($a+$b) ."<BR>";
print ("La suma de $a + $b es: " . $a . "+" . $b . "=" . ($a+$b) ."<BR>");
echo "La suma de $a + $b es: " . $a . "+" . $b . "=" . ($a+$b) ."<BR>";
echo "La suma de $a + $b es: " , $a , "+" , $b . "=" , ($a+$b) ."<BR>";
echo "La suma de $a + $b es: " , $a , "+" , $b , "=" , $a+$b ,"<BR>";
# guardemos ahora el resultado de esa operación en una nueva variable
$c=$a+$b;
/*ahora presentemos el resultado utilizando esa nueva variable
 adviertiendo el la salida */
print ("Resultados recogidos en una nueva variable<br>");
print "La suma de $a + $b es: " . $a . "+" . $b . "=" . $c ."<BR>";
print ("La suma de $a + $b es: " . $a . "+" . $b . "=" . $c ."<BR>");
echo "La suma de $a + $b es: " . $a . "+" . $b . "=" . $c ."<BR>";
echo "La suma de $a + $b es: " , $a , "+" , $b . "=" , $c ."<BR>";
echo "La suma de $a + $b es: " , $a , "+" , $b , "=" , $c ,"<BR>";
/* modifiquemos ahora los valores de $a y $b comprobando que el cambio
   no modifica lo contenido en la variable $c */
$a=513; $b=648;
print ("<br> C sigue valiendo: " . $c ."<br>");
# experimentemos con los paréntesis en un supuesto de operaciones combinada
# tratemos de sumar la variable $a con la variable $b
# y multiplicar el resultado por $c.
# Si escribimos print($a+$b*$c) nos hará la multiplicación antes que la suma
print "<br>No he puesto paréntesis y el resultado es: ".($a+$b*$c);
# Si escribimos print(($a+$b)*$c) nos hará la suma y luego multiplicará
print "<br>He puesto paréntesis y el resultado es: ".(($a+$b)*$c);
?>
ejemplo33.php

Operaciones aritméticas
Operación Sintaxis A B Resultado
Suma$a+$b12-7.34.7
Diferencia$a-$b12-7.319.3
Producto$a*$b12-7.3-87.6
Cociente$a/$b12-7.3-1.64383561644
Cociente entero(int)($a/$b)12-7.3-1
Resto de la división$a%$b1252
Potencias abpow($a,$b)125248832
Potencias abpow($a,$b)-7.3-3-0.00257058174836
Raíz cuadrada Sqrt($a)12 3.46410161514
Raíz cuadrada Sqrt($a)-7.3 NAN
Raíz enésima pow($a,(1/$b)1232.28942848511
Valor absoluto Abs($b) -7.37.3

Al realizar una operación cuyo resultado no es un número real PHP devuelve la cadena NaN tal como puedes ver en el ejemplo de la raíz cuadrada de un número negativo.


Redondeo de resultados

PHP dispone de tres opciones de redondeo:

floor($z)

Redondeo por defecto

ceil($z)

Redondeo por exceso

round($z)

Redondeo tradicional

Redondeos
tipo Sintaxis A Resultado
Parte entera (int)$a1212
Parte entera (int)$a-7.3-7
Parte entera (int)$a-13.8546-13
Parte entera (int)$a-24.5-24
Parte entera (int)$a13.854613
Parte entera (int)$a24.524
Redondeo por defecto floor($a)1212
Redondeo por defecto floor($a)-7.3-8
Redondeo por defecto floor($a)-13.8546-14
Redondeo por defecto floor($a)-24.5-25
Redondeo por defecto floor($a)13.854613
Redondeo por defecto floor($a)24.524
Redondeo por exceso ceil($a)1212
Redondeo por exceso ceil($a)-7.3-7
Redondeo por exceso ceil($a)-13.8546-13
Redondeo por exceso ceil($a)-24.5-24
Redondeo por exceso ceil($a)13.854614
Redondeo por exceso ceil($a)24.525
Redondeo round($a)1212
Redondeo round($a)-7.3-7
Redondeo round($a)-13.8546-14
Redondeo round($a)-24.5-25
Redondeo round($a)13.854614
Redondeo round($a)24.525

Orden de operación

Cuando una misma instrucción contiene una secuencia con varias operaciones el orden de ejecución de las mismas sigue los mismos criterios que las matemáticas. No se realiza una ejecución secuencial sino que se respeta el orden de prioridad matemático. Es decir, las potencias y raíces tienen prioridad frente a los productos y los cocientes, y estos, son prioritarios respecto a la suma y las diferencias.

Igual que en matemáticas se pueden utilizar los paréntesis para modificar el orden de ejecución de las operaciones, e igual que allí PHP también permite encerrar paréntesis dentro de paréntesis.

  ¡Cuidado!  

Cuando realices operaciones combinadas, no olvides establecer –mediante paréntesis– las prioridades que sean necesarias. ¡No temas abusar de ellos! Te evitarán muchos problemas.

Punto flotante y precisión arbitraria

Las funciones aritméticas que estamos estudiando utilizan la sintaxis de punto flotante cuya precisión es limitada y, aunque depende del sistema, PHP típicamente utiliza el formato de doble precisión IEEE 754, el cual puede dar un error relativo máximo por aproximación del orden de 1.11*10–16.

Las operaciones aritméticas más elementales nunca van a dar grandes errores aunque la dimensión de estos podrá irse incrementando a medida que se concatenar varios de esos errores simples en operaciones compuestas.

Hay que tener en cuenta la existencia de fracciones que se pueden representar de forma exacta como números de punto flotante en base 10 (por ejemplo 1/10 ó 7/10) pero que carecen de esa exactitud al ser expresados en base 2 que es la usada internamente por PHP.

Así pues, hemos de tener cuidado al considerar números de coma flotante hasta su último dígito por los imprevisibles efectos –sobretodo a la hora de la comparación– de esos errores en el resultado.

Para operaciones matemáticas que necesiten una mejor precisión PHP (innecesaria en el ámbito cotidiano y limitada a casos muy puntuales del ámbito científico) ofrece la calculadora binaria que soporta números de cualquier tamaño y precisión representados como cadenas. Las funciones que utilizan esa forma de cálculo son las siguientes:

bcadd($a,$b,c)

Devuelve la suma de los valores numéricos contenidos en las cadenas $a y $b con una precisión (número de cifras decimales) especificada por el número entero especificado en el parámetro c.

bcsub($a,$b,c)

Devuelve la diferencia entre los valores numéricos contenidos en las cadenas $a y $b con una precisión (número de cifras decimales) especificada por el número entero especificado en el parámetro c.

bcmul($a,$b,c)

Devuelve el producto de los valores numéricos contenidos en las cadenas $a y $b con una precisión (número de cifras decimales) especificada por el número entero especificado en el parámetro c.

bcdiv($a,$b,c)

Devuelve el resultado de dividir los valores numéricos contenidos en las cadenas $a y $b con la precisión especificada por el número entero contenido en el parámetro c.

bcmod($a,$b)

devuelve el resto de la división entera de los valores contenidos en las cadenas $a y $b.

bcpow($a,$b,c)

Devuelve el resultado de elevar el valor numérico contenido en la cadena $a a la potencia expresada por la cadena $b dando el resultado con la cantidad de decimales señalada por el parámetro c.


bcsqrt($a,c)

Devuelve la raíz cuadrada del valor numérico contenido en la cadena $a con la cantidad de decimales señalada por el parámetro c.

bccomp($a,$b,c)

Compara los valores contenidos en las cadenas $a y $b teniendo en cuenta únicamente el número de decimales especificados en c. Si $a>$b devuelve 1. Si las magnitudes comparadas son iguales devuelve 0 y si son distintas devuelve 1.

Si comparamos $a='3.456' (es necesario indicar siempre los valores como cadenas) con $b='3.45' obtendremos como resultado:

bccomp($a,$b,0)=0   Compara 3 con 3 que obviamente son iguales
bccomp($a,$b,1)=0   Compara 34 con 34. Son iguales y por tanto devuelve cero
bccomp($a,$b,2)=0   Compara 345 con 345. Son iguales y por tanto devuelve cero
bccomp($a,$b,3)=1   Compara 3456 con 3450. No son iguales y por tanto devuelve uno

En el cuadro puedes ver, señalados en rojo, los resultados de efectuar la misma operación utilizando el operador de coma flotante y estas funciones de precisión arbitraria. Si comparas las diferencias en los resultados obtenidos con cada una de ellas podrás darte idea del error provocado por los inevitables redondeos de la operación con coma flotante.

Comparación de punto flotante y precisión arbitraria

Comparación de funciones matemáticas
Operación Variable Valor
S
U
M
A
$A"12345678910123456789012345678901234567890"
$B"45678910123456789012345678901234567890123"
bcadd($A,$B,0)58024589033580245801358024580135802458013
$a=(double)$A1.23456789101E+40
$b=(double)$B4.56789101235E+40
$a+$b5.80245890336E+40 ó
58024589033580236333428572634998418440192
$C"0.0002345678902"
$D"0.00000000000000000000000000000000000000001523786"
bcadd($C,$D,50)0.00023456789020000000000000000000000000001523786000
$c=(double)$C0.0002345678902
$d=(double)$D1.523786E-41
$c+$d0.0002345678902 ó
0,00023456789020000001029161995624860992393223568797
R
E
S
T
A
$A"12345678910123456789012345678901234567890"
$B"45678910123456789012345678901234567890123"
bcsub($A,$B,0)-33333231213333332223333333222333333322233
$a=(double)$A1.23456789101E+40
$b=(double)$B4.56789101235E+40
$a-$b-3.33332312133E+40 ó
-33333231213333327795815413198205132734464
$C"0.0002345678902"
$D"0.00000000000000000000000000000000000000001523786"
bcsub($C,$D,50)0.00023456789019999999999999999999999999998476214000
$c=(double)$C0.0002345678902
$d=(double)$D1.523786E-41
$c-$d0.0002345678902 ó
0,00023456789020000001029161995624860992393223568797
P
R
O
D
U
C
T
O
$A"12345678910123456789012345678901234567890"
$B"45678910123456789012345678901234567890123"
bcmul($A,$B,0)56393715734858534797546128354926080723008626986848
1383972550423718379870903950470
$a=(double)$A1.23456789101E+40
$b=(double)$B4.56789101235E+40
$a*$b5.63937157349E+80 ó
56393715734858529559076134525051001632068799181691
5078270593363632973621514731520
$C"0.0002345678902"
$D"0.00000000000000000000000000000000000000001523786"
bcmul($C,$D,62)0.000000000000000000000000000000000000000000003574
312671362972
$c=(double)$C0.0002345678902
$d=(double)$D1.523786E-41
$c*$d3.57431267136E-45 ´0
0,000000000000000000000000000000000000000000003574
31267136297184
D
I
V
I
S
I
Ó
N
$A"12345678910123456789012345678901234567890"
$B"45678910123456789012345678901234567890123"
bcdiv($A,$B,30)0.270270872854818178953756836882
$a=(double)$A1.23456789101E+40
$b=(double)$B4.56789101235E+40
$a/$b0.270270872855 ó
0,270270872854818211550309570157
$C"0.0002345678902"
$D"0.00000000000000000000000000000000000000001523786"
bcdiv($C,$D,30)15393755435474535138136194977509965310.08947450626
2690430283517501801
$c=(double)$C0.0002345678902
$d=(double)$D1.523786E-41
$c/$d1.53937554355E+37 ó
15393755435474536238109275036946792448,00000000000
0000000000000000000
R
E
S
T
O
S
$A"12345678910123456789012345678901234567890"
$B"57"
bcmod($A,$B)19
$a=(double)$A1.23456789101E+40
$b=(double)$B57
$a % $b0
P
O
T
E
N
C
I
A
$A"12345678910123456789012345678901234567890"
$B"13"
bcpow($A,$B)15477282435120092620517640487873307882539433894477
02478876805675247359287360605519476488004915460644
30130253272627846453956411651820029120439549209342
64779279536097719586538292066102759581864670705845
47341619065960659102701030110334399943453939049941
81961179086427277645221130645386339095405377300948
55610257804029129290263282188925049521874093123594
94558994966581650612470024575134583192369561297975
69626211024080786875604177270092747586939296603680
65512433192215011092075340601280601173670507434702
7729224690000000000000
$a=(double)$A1.23456789101E+40
$b=(double)$B13
pow($a, $b)INF ó
inf
 
 
R
A
I
Z
 
 
C
U
A
D
R
A
D
A
$A"12345678910123456789012345678901234567890"
$B"13"
bcsqrt($A,15)111111110651111110153.9111071478030905799220364
$a=(double)$A1.23456789101E+40
$b=(double)$B13
Sqrt($a)1.11111110651E+20 ó
111111110651111112704,0000000000000000000000000

Aunque las diferencias de resultados puedan parecer muy grandes en valor absoluto (hemos exagerado premeditadamente los valores operados (tanto en valores grandes como en valores pequeños) los errores relativos son de escasa significación. En la inmensa mayoría de las situaciones (por no decir todas las cotidianas) resulta suficiente utilizar los operadores de coma flotante.