Google sabe mucho más de ti de lo que te imaginas

Bueno esta entrada no es sobre programación pero es interesante así que lo comparto.



Google recopila datos de los usuarios, de los que a veces éstos no tienen idea.
Por: Gabriela Vaz

La primera vez que tuve cierta conciencia de la información que Google manejaba sobre mí sin que yo se la hubiese proporcionado expresamente fue el año pasado, sobre el final de unas vacaciones en el exterior. El día de mi regreso a Uruguay, una alerta sonó en mi celular y al mirar la pantalla me encontré con un recordatorio del número de vuelo, un aviso de cuántas horas faltaban para el despegue del avión y el dato preciso de a qué distancia estaba en ese momento del aeropuerto, con tiempos estimados de cuánto demoraría en llegar si iba hasta allí en auto.

Primero me desconcertó de dónde habían sacado esa información; en ningún momento había yo llenado formulario alguno o escrito en el buscador —ni en ningún rincón de Internet— el número de vuelo, ni la fecha de partida o regreso. Ni siquiera había forma, pensaba, de que supieran que estaba fuera del país. Hasta que entendí: la agencia de viajes donde compré los pasajes me había enviado al correo de Gmail el itinerario, dos meses antes. Y listo: Google lo sabía todo.

Así y todo, esa sorpresa fue menos impactante que la que sentí semanas atrás, cuando ingresé al link maps.google.com/ locationhistory, luego de leer acerca de esto en un foro de Internet. Si tiene un celular con Android y entra a esta dirección logueado con la cuenta de Google que tiene sincronizada en el teléfono, puede suceder que lo que vea lo deje atónito. Me encontré con el registro detallado, dibujado en mapas, de dónde había estado cada día durante los últimos tres años; en Uruguay, en Brasil, en Estados Unidos… donde fuera, Google tenía el recorrido preciso de cada calle por la que yo —o al menos el celular— había pasado.

Es verdad que no es noticia nueva. Desde 2009, Google publica una transparente herramienta llamada Dashboard, que permite a los usuarios saber exactamente qué tipo de datos tiene el buscador sobre ellos y de dónde los saca. Incluso brinda la posibilidad de limitar (no del todo, pero bastante) la información que puede almacenar. Sin embargo, la intromisión de los buscadores de Internet en los asuntos personales de los usuarios es un tema cada vez más tratado. De acuerdo a una encuesta que el último año realizó la firma de investigación de consumo Survata, a los estadounidenses les preocupa más el acceso a su información personal por parte de Google que por parte de su jefe, sus padres, su pareja o hasta la propia Agencia Nacional de Seguridad.

“Google sabe mucho”, dijo el bloguero Ondrej Prostrednik, autor de varios artículos sobre el tema, al Washington Post. “La gente fuera de Google apenas puede imaginarlo. Pero es importante darse cuenta de que somos nosotros quienes le damos toda la información que saben”.

Es que, en muchas instancias, el propio usuario aprueba ese seguimiento de Google ya sea firmando por un servicio u optando por un teléfono con Android. El tema es que no se tiene en cuenta que, al menos que expresamente configuremos las cuentas para que no sea así, cada dato es almacenado para siempre en un lugar centralizado. “El pequeño y ordinario acto de mandar un mail o hacer una búsqueda o buscar direcciones puede resultar revelador en sí mismo. Pero cuando compilas miles de mails y búsquedas y direcciones a través del tiempo, algo que Google hace, terminas con algo mucho más intimidante; algo que no está muy lejos de ser un retrato detallado de tu vida y tus intereses”, escribió en el Post la periodista estadounidense Caitlin Dewey.
Cómo lo hace.

Si tiene activado el historial de búsquedas, Google registra su accionar en distintas categorías. Por ejemplo, las horas y los días de la semana en que está más activo, las fechas del año en las que realizó más búsquedas, o los sitios a los que entra más seguido. Puede descubrirlo en history.google.com.

Tenga o no una cuenta en Google Plus, la red social del buscador, la empresa tiene un perfil básico de usted, elaborado a partir de sus conductas de navegación en Internet: sabe qué edad tiene, cuál es su sexo, qué idiomas habla y algunos de sus gustos en función de las búsquedas que realiza a diario. Esta es la información que utiliza para definir qué publicidad mostrarle mientras navega. Para saber qué datos tiene, puede entrar a www.google.com/ads/preferences

La empresa también rastrea qué dispositivos utiliza para ingresar a sus servicios. En el link security.google.com/settings/security/activity es posible ver esos datos. Por ejemplo, allí verá si su cuenta fue ingresada desde una Mac en Montevideo hace cinco minutos, o bien desde equis modelo de teléfono celular ubicado en Madrid hace una semana. Es muy útil para saber si alguien que no es usted ha entrado a su cuenta.

Considere los servicios de Google que usted probablemente use a diario y entenderá que hay muy poco que quede fuera de su órbita. Si tiene un teléfono con Android, la empresa puede registrar su locación y velocidad de datos. Si tiene una cuenta de YouTube, Google sabe no solo qué videos sube, sino también cuáles mira (para ver su historial de reproducciones, ingrese a www.youtube.com/feed/history y para ver lo que ha buscado en la red de videos, el sitio es www.youtube.com/feed/history/search_history). Con Google Play, conoce las aplicaciones que usa. Entre los contactos de Google y el chat, tiene una idea bastante acertada de quiénes son sus amigos. Y mientras los datos de su navegación se agregan a la información de esos servicios, si visita sitios que usen los softwares Google Ads o Google Analytics, el buscador generalmente también sabe qué mira y qué clickea. De acuerdo a un reporte de la Universidad de Berkeley, Google puede rastrear el comportamiento de los usuarios de 88% de los dominios de Internet. Pues sí: hay muy pocos rincones de la vida moderna que Google no toca.

Tal como apunta el Washington Post, “nada de esto es malicioso per se. Solo es la consecuencia necesaria de una compañía proveyendo un rango tan increíble de servicios y convirtiéndose en una parte tan inextricablemente incrustada en las vidas de cientos de millones de personas”. Limitar ese poder depende de usted. Empiece por tomar conciencia.
Respalde los datos que le da al buscador.

“Es importante que puedas acceder a tus datos de Google cuándo y dónde quieras, ya sea para importarlos a otros servicios o simplemente para crear una copia de tus archivos”, se lee en la página de ayuda al usuario de Google, acerca de su herramienta www.google.com/ settings/take-out, que permite respaldar toda la información que la empresa almacena, obtenida a través de sus servicios. “En general, los usuarios no se preocupan por saber si pueden recuperar sus datos de un producto hasta que deciden dejar de utilizarlo”, agrega.
Se pueden poner límites.

“Somos muy conscientes de la confianza que los usuarios han puesto en nosotros y de nuestra responsabilidad para proteger su privacidad e información”, declaró Google en un reporte de 2009.

Para demostrar que no eran solo palabras, la compañía instauró entonces el Dashboard, una herramienta que “blanquea” qué datos poseen de cada usuario, y decidió dar la chance de limitar cuántos datos se le permite almacenar. Usted puede apagar las herramientas que rastrean su historial personal de búsquedas y que sincroniza el uso de Chrome entre sus computadoras. También puede optar por eliminar los anuncios basados en intereses; esos mensajes que a veces asustan invitándolo a comprar una cámara justo después de que buscó información sobre el tema.
Documentos y aniversarios.

Blogs, noticias, imágenes, videos… a Google nada parece escapársele de las manos. Desde que lanzó la aplicación Calendar, que te permite recordar cumpleaños, citas, reuniones o tareas que no quieres olvidar bajo ningún punto de vista, el buscador conoce hasta la fecha de aniversario con tu pareja o cuándo tenés que tomarte la pastilla anticonceptiva. Y te envía un correo electrónico para recordártelo. Pero la empresa se pasea del ámbito íntimo al laboral muy cómodamente. En enero de 2010, Google presentó al mundo sus procesadores de texto y hojas de cálculos. Con el paso del tiempo, se sumaron funcionalidades, como la posibilidad de almacenar hasta 5 gigas. Son muchos quienes se muestran escépticos ante esta “nube”, ya que el gigante dispone información de todo tipo y color.


Fuente:

http://www.elpais.com.uy/domingo/google-demasiado.html#

http://www.elmundoalinstante.com/google-sabe-mucho-mas-de-ti-de-lo-que-tu-te-imaginas/

Calculadora de Prestamos en PHP

En esta oportunidad les dejamos una clase que se encarga de realizar cálculos sobre prestamos, como ser calcular la cuota, la tasa de interés o realizar el cuadro de pagos de un préstamo.
La particularidad de esta clase es que todos sus cálculos están basados en la librería bcmath de php que según el manual es “Para operaciones matemáticas de precisión arbitraria, PHP ofrece la Calculadora Binaria, la cual admite números de cualquier tamaño y precisión, representados como strings.”, esto nos permite hacer cálculos con números realmente grandes y con la precisión que nosotros establezcamos.
Bueno ahora la clase.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
<?php
/**
 * Clase Prestamo
 * Clase con la cual se puede realizar calculos sobre prestamos que no son 
 * a cuota constantes. Permite calculo de tasa de interes, amortizacion de un
 * periodo dado, cuota de un periodo etc.
 * Se utilizan las operaciones de precision arbitraria de php.
 * 
 * @package     Finanzas Creado para el proyecto Agenor.
 * @copyright   (2013 - 2013) - ObjetivoPHP
 * @license     Gratuito (Free) http://www.opensource.org/licenses/gpl-license.html
 * @author      Marcelo Castro, ObjetivoPHP
 * @version     0.1.0 (01/07/2013 - 01/07/2013)
 */
class Prestamo
{
    /**
     * Precision de los calculos a realizar.
     * @var integer 
     */
    private $_precision = 12;
 
    /**
     * Cantidad de iteraciones para los calculos de funciones externas.
     * @var integer 
     */
    private $_iterador  = 12;
 
    /**
     * Tasa de Interes real del Prestamo, expresada en el lapso de tiempo
     * de los pagos. Si se tiene una tasa anual y se requiere mensual usar el 
     * metodo convertirTasa.
     * @var double
     */
    private $_tasaInteres;
 
    /**
     * Monto total del prestamo solicitado al Momento 0.
     * @var double 
     */
    private $_capital;
 
    /**
     * Arreglo Conteniendo los pagos en cada periodo. El indice es el periodo y
     * el monto el valor del arreglo.
     * @example array(1 => 10000, 2=> 3750); Significa que el pago del 1er Mes es
     * 10.000 y el segundo 3.750.-
     * @var array 
     */
    private $_pagos = array();
 
    /**
     * Contiene la tabla de pagos del peridodo.
     * @var array
     */
    private $_tablaPagos = array();
 
    /**
     * Constructor de Clase.
     * @param   integer $precision  Establece con cuantos numeros se mostrara el resultado.
     */
    public function __construct($precision = 12)
    {
        if (is_int($precision) && $precision > 0) {
            $this->_precision = $precision;
        }
 
        bcscale($this->_precision);
    }
 
    /**
     * Cofigura la tasa de interes que tendra el Prestamo.
     * @param   double  $tasa       Valor de la tasa de interes.
     * @param   integer $periodos   En cuantos periodos del prestamo esta expresada.
     * @example Si la tasa nos la dan anual para un prestamo de pago mensual entonces
     *          periodos va a ser igual a 12.-
     * @throws  Si el valor de la tasa de interes no es valido lanza un error.
     */
    public function setTasaInteres($tasa, $periodos = 1)
    {
        if (!is_numeric($tasa)) {
            throw new \Exception('Tasa de Interes No Valida');
        }
 
        if (is_int($periodos)) {
            $tasa   = bcadd('1', $tasa);
            $period = bcdiv('1', $periodos);
            $tasa   = $this->bcpowx($tasa, $period, $this->_iterador);
            $this->_tasaInteres = bcsub($tasa, '1');
        }
    }
 
    /**
     * Establece las iteraciones para el calculo de potencias complejas.
     * @param   integer $iterador   Numero de iteraciones a realizar.
     */
    public function setIterador($iterador)
    {   
        if (is_int($iterador) && $iterador >= 10) {
            $this->_iterador = $iterador;
        }
    }
 
    /**
     * Convierte la tasa de interes de un periodo a otro.
     * @param   double  $tasa
     * @param   integer $de     periodo actual de la tasa de interes (generalmente 1).
     * @param   integer $a      Al periodo que se quiere convertir (Ej.: Anual = 12, si de  1).
     * @return  double          Retorna la tasa de interes convertida al Periodo establecido.
     */
    public function convertirTasa($tasa, $de, $a)
    {
        $retorno        = 0;
        if (is_int($de) && is_int($a) && is_numeric($tasa)) {
            $tasa       = bcadd('1', $tasa);
            $period     = bcdiv($a, $de);
            $tasa       = $this->bcpowx($tasa, $period, $this->_iterador);
            $retorno    = bcsub($tasa, '1');
        }
        return $retorno;
    }
 
    /**
     * Retorna la Tasa de interes Calculada.
     * @return duble
     */
    public function getTasaInteres()
    {
        return $this->_tasaInteres;
    }
 
    /**
     * Calcula la tasa Interna de Retorno de un prestamo o inversion.
     * @return double
     */
    public function calcularTasaInteres()
    {   
        if (is_numeric($this->_capital) && $this->_capital > 0 && array_sum($this->_pagos) >= $this->_capital ) {
            $tirP               = array_sum($this->_pagos) / $this->_capital;  
            $this->_tasaInteres = $this->_tir(0, $tirP, 0);             
        } else {
            throw new \Exception('Faltan parametros para calcular la tasa de interes.');
        }
 
        return $this->_tasaInteres;
    }
 
    /**
     * Calcula la tir de una inversion.
     * Se calcula en base al teorema de bolzano.
     * @param   double  $a          Extremo inferior supuesto de la Tasa de Interes.
     * @param   double  $b          Extremo superior supuesto de la tasa de interes.
     * @param   double  $tirc       Tir que esta siendo calculada.
     * @param   double  $precision  Precision que se quiere del resultado.
     * @return  double
     */
    private function _tir($a, $b, $tirc)
    {    
        $tir    = bcdiv(bcadd($a, $b), 2);
        $van    = 0;
        foreach ($this->_pagos as $cuota => $valor) {
            //$van    = $van + $valor / pow((1 + $tir ), $cuota);
            $van = bcadd($van, bcdiv($valor, bcpow(bcadd('1', $tir), $cuota)));
        }
        $van = bcsub($van, $this->_capital);
 
        if (bccomp($tirc, $tir) == 0) {
            return $tir;
        } else {
            if ($van > 0) {
                return $this->_tir($tir, $b, $tir);
            } else {
                return $this->_tir($a, $tir, $tir);
            }
        }
    }
 
    /**
     * Establece el dinero pedido en prestamo o el valor de la secuencia de
     * pagos al momento 0.
     * @param   double  $monto  Capital, dinero pedido.
     * @throws  Error si no se ingresa un monto valido de capital.
     */
    public function setCapital($monto)
    {
        if (is_numeric($monto)) {
            $this->_capital = $monto;
        } else {
            throw new \Exception('No se establecio un monto valido.');
        }
    }
 
    /**
     * Calcula la cuota de un prestamo para una cuota constante.
     * @param   integer $periodos   Cantidad de Periodos de los pagos consecutivos.
     * @return  double              Cuota a pagar en cada periodo.
     */
    public function calcCuota($periodos)
    {
        $i          = $this->_tasaInteres;
        $n          = (int) $periodos;
        if (bccomp(0, $this->_tasaInteres) == 0) {
            $cuota  = bcdiv($this->_capital, $n);
        } else {
            $numerador  = bcmul($i, bcpow(bcadd('1', $i), $n));
            $divisor    = bcsub(bcpow(bcadd('1', $i), $n), '1');
            $cuota      = bcmul($this->_capital, bcdiv($numerador, $divisor));            
        }
        return $cuota;
    }
 
    /**
     * Configura los pagos.
     * @param   integer     $desde  Cuota desde donde comienza el pago.
     * @param   integer     $hasta  Cuota hasta donde se paga.
     * @param   double      $cuota  Valor de la cuota.
     * @throws \Exception   Si no se ingresa un monto de cuota valido.
     */
    public function pagos($desde, $hasta, $cuota)
    {
        $desde = (int) $desde;
        $hasta = (int) $hasta;
 
        if (is_numeric($cuota)) {
            for($i = $desde; $i <= $hasta; $i++) {
                $this->_pagos[$i] = $cuota;
            }
        } else {
            throw new \Exception('La cuota no tiene un valor valido.');
        }
    }
 
    /**
     * Genera una tabla de Pagos de un prestamo.
     * @param   boolean $amortConst Establece si la amortizacion es constante o variable.
     * @return  array
     * @throws \Exception   Si el periodo de pago es menor o igual a 0.
     */
    public function calcTablaDePagos($amortConst = false)
    {
        $i      = $this->_tasaInteres;
        end($this->_pagos);
        $datos  = each($this->_pagos);
        $n      = $datos['key'];
        if ($n <= 0) {
            throw new \Exception('El periodo de pago no puede ser cero.');
        }
 
        if ($amortConst) {
            // Si tenemos Amortizacion Constante entonces la amortizacion es el 
            // Capital dividido el numero de cuotas, si no es asi se toma el 
            // arreglo de pagos para calcular la tabla.
            $c  = bcdiv($this->_capital, $n);
        }
 
        $tabla      = array();
        $tabla[0]['Monto']  = $this->_capital;
        $tabla[0]['Saldo']  = $this->_capital;
        for ($p = 1; $p <= $n; $p++) {
            $tabla[$p]['Periodo']   = $p;
            $tabla[$p]['Monto']     = $tabla[($p-1)]['Saldo'];
            $interes        = bcmul($tabla[$p]['Monto'], $this->_tasaInteres);
            if ($amortConst) {
                $tabla[$p]['Amortizacion']  = $c;
            } else {
                $tabla[$p]['Amortizacion']  = bcsub($this->_pagos[$p], $interes);
            }
            $tabla[$p]['Interes']       = $interes;
            $tabla[$p]['Cuota']     = bcadd($tabla[$p]['Amortizacion'], $tabla[$p]['Interes']);
            $tabla[$p]['Saldo']     = bcsub($tabla[$p]['Monto'], $tabla[$p]['Amortizacion']);
        }
        array_shift($tabla);
        $this->_tablaPagos = $tabla;
        return $tabla;
    }
 
    /**
     * Genera una tabla de prestamo.
     * Metodo usado para ver la tasa de prestamo de ejemplo.
     * No se debe incluir.
     */
    public function getHtmlPrestamo($dec = 2)
    {
        if (count($this->_tablaPagos) < 1) {
            throw new \Exception('No se creo la tabla de pagos. Ejecute calTablaDePagos');
        }
        // Genero el HTML
        echo '<table style="border:solid;" border="1">';
        echo '<td>Periodo</td><td>Monto</td><td>Amort.</td><td>Interes</td><td>Cuota</td><td>Saldo</td>';
        foreach ($this->_tablaPagos as $value) {
            echo '<tr>' . PHP_EOL;
            echo '<td>' . number_format($value['Periodo'], 0, ',', '.')         . '</td>' . PHP_EOL;
            echo '<td>' . number_format($value['Monto'], $dec, ',', '.')        . '</td>' . PHP_EOL;
            echo '<td>' . number_format($value['Amortizacion'], $dec, ',', '.') . '</td>' . PHP_EOL;
            echo '<td>' . number_format($value['Interes'], $dec, ',', '.')      . '</td>' . PHP_EOL;
            echo '<td>' . number_format($value['Cuota'], $dec, ',', '.')        . '</td>' . PHP_EOL;
            echo '<td>' . number_format($value['Saldo'] , $dec, ',', '.')       . '</td>' . PHP_EOL;
            echo '</tr>' . PHP_EOL;
        }
 
        echo '</table>';  
    }
 
 
    ############################################################################
    # FUNCIONES EXTRAIDAS DEL MANUAL DE PHP                                    #
    # http://www.php.net/manual/es/ref.bc.php                                  #
    ############################################################################
    
    /**
     * Computes the factoral (x!).
     * @author Thomas Oldbury.
     * @license Public domain.
     */
    public function bcfact($fact)
    {
        if($fact == 1) return 1;
        return bcmul($fact, $this->bcfact(bcsub($fact, '1')));
    }    
 
    /**
     * Computes e^x, where e is Euler's constant, or approximately 2.71828.
     * @author Thomas Oldbury.
     * @license Public domain.
     */
    public function bcexp($x, $iters = 7)
    {
        /* Compute e^x. */
        $res = bcadd('1.0', $x);
        for($i = 0; $i < $iters; $i++) {
            $res += bcdiv(bcpow($x, bcadd($i, '2')), $this->bcfact(bcadd($i, '2')));
        }
        return $res;
    }
 
    /**
     * Computes ln(x).
     * @author Thomas Oldbury.
     * @license Public domain.
     */
    public function bcln($a, $iters = 10)
    {
        $result = "0.0";
        for($i = 0; $i < $iters; $i++) {
            $pow = bcadd("1.0", bcmul($i, "2.0"));
            //$pow = 1 + ($i * 2);
            $mul        = bcdiv("1.0", $pow);
            $fraction   = bcmul($mul, bcpow(bcdiv(bcsub($a, "1.0"), bcadd($a, "1.0")), $pow));
            $result     = bcadd($fraction, $result);
        }
 
        $res = bcmul("2.0", $result);
        return $res;
    }
 
    /**
     * 
     * Computes a^b, where a and b can have decimal digits, be negative and/or very large.
     * Also works for 0^0. Only able to calculate up to 10 digits. Quite slow.
     * @author Thomas Oldbury.
     * @license Public domain.
     */
    public function bcpowx($a, $b, $iters = 25)
    {
        $ln = $this->bcln($a, $iters);
        return $this->bcexp(bcmul($ln, $b), $iters);
    }
}

Lo mas importante que si se va a utilizar precisiones grandes y muchas iteraciones importante para el calculo de tasas de interés es que se configure el limite de ejecución.

set_time_limit(0);

Con esto nuestra clase dispondrá de todo el tiempo posible para ejecutarse.
Ahora un ejemplo sencillo.
Calcular la tasa de interés de un préstamo de $ 10.000 a pagar en 12 cuotas de 1.200 y luego realizar la tabla del prestamo.

// Creamos el objeto préstamo y le decimos que queremos una exactitud de 10 dígitos después de la coma.
$prestamo   = new Prestamo(10);
// Configuramos el valor que pedimos de préstamo.
$prestamo->setCapital('10000');
// Establecemos como vamos a pagar el préstamo.
// En este caso de la cuota 1 a la 10 $ 1200.
// Se pueden definir varios tramos de pago de distinto valor.
$prestamo->pagos(1, 10, '1200');
// Calculamos la tasa de interes que nos estan cobrando.
$b = $prestamo->calcularTasaInteres();
// Mostramos la tasa de interés mensual
echo '<br>T.int.mensual: ' . $b;
// con el metodo convertirTasa la pasamos a anual y la mostramos.
// Pasamos la tasa $b, en la unidad que esta expresada 1 mes y el año son 12 meses.
echo '<br>T.int.anual: ' . $prestamo->convertirTasa($b, 1, 12);
// Calculamos la tabla de pagos
$t = $prestamo->calcTablaDePagos();
// Y la mostramos como html.
$prestamo->getHtmlPrestamo();

La salida seria :

T.int.mensual: 0.0346015380T.int.anual: 0.5041025038
Periodo Monto Amort. Interes Cuota Saldo
1 10.000,00 853,98 346,02 1.200,00 9.146,02
2 9.146,02 883,53 316,47 1.200,00 8.262,48
3 8.262,48 914,11 285,89 1.200,00 7.348,38
4 7.348,38 945,73 254,27 1.200,00 6.402,64
5 6.402,64 978,46 221,54 1.200,00 5.424,18
6 5.424,18 1.012,31 187,69 1.200,00 4.411,87
7 4.411,87 1.047,34 152,66 1.200,00 3.364,52
8 3.364,52 1.083,58 116,42 1.200,00 2.280,94
9 2.280,94 1.121,08 78,92 1.200,00 1.159,87
10 1.159,87 1.159,87 40,13 1.200,00 0,00

Espero les sea de utilidad y recordar que es mas util para numeros que requieren de mucha precisión.
Saludos y hasta la proxima.

Convertir Excel en Array y algo Mas…

Bueno ya que muchos a causa de la aplicación DEAME3P me preguntan como extraer datos de Excel, aquí les voy a dejar una clase que convierte un archivo Excel ya sea xlsx o xls en un arreglo y nos da alguna función, para permitirnos hacer algo mas.

Consideraciones:
Tener en cuenta que como carga el Excel a un Arreglo no es recomendable para archivos excel de muchos datos.
Los datos deben comenzar en la Columna A – Fila 1
El archivo excel deberá contener en la primera fila los encabezados o títulos y de ser posible se deberá otorgar una columnas en donde sus datos sean únicos (no se repitan), que serán usados como claves.
La mas importante de todas es que hace uso de la Libreria PHPExcel de Codeplex, por lo cual deberan hacer los requiere correspondientes.

Ahora un poco de codigo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
<?php 
// Lanza todos los errores
error_reporting(E_ALL  | E_STRICT);
// Tiempo ilimitado para el script
set_time_limit(0);
 
require_once 'PHPExcel/Classes/PHPExcel.php';
require_once 'PHPExcel/Classes/PHPExcel/IOFactory.php';
 
class ExcelToArray
{
    /**
     * Contiene Las Extenciones Permitidas para Excel.
     * @var Array 
     */
    private $_tipoExcel = array('xlsx'  => 'Excel2007',
                                'xls'   => 'Excel5');
 
    /**
     * Contiene la Cantidad de Columnas del Archivo Excel.
     * @var integer 
     */
    private $_columnas  = 0;
 
    /**
     * Contiene la Cantidad de Filas del Archivo Excel.
     * @var integer 
     */
    private $_filas     = 0;
 
    /**
     * Contiene el Titulo que sera el Identificador.
     * @var string 
     */
    private $_id;
 
    /**
     * Contiene el Arreglo Generado a partir del Excel.
     * @var array
     */
    private $_excel     = array();
 
    /**
     * Contiene los Encabezados del Archivo Excel.
     * @var array 
     */
    private $_titulos   = array();
 
    /**
     * Contiene la ruta y nombre del Archivo.
     * @var type 
     */
    private $_file;
 
    /**
     * Contiene el Tipo del Archivo Excel para PHPExcel.
     * @var string 
     */
    private $_tipoPHPExcel;
 
    /**
     * Contiene el objeto tipo Hoja de calculo.
     * @var PHPExcel_Worksheet
     */
    private $_objWorksheet;
 
 
    /**
     * Constructor de Clase.
     * @param   string  $file   Ruta y nombre del Archivo.
     * @throws  Exception       Lanza exepcion si el archivo no existe o si,
     *                          no es de una extencion valida.
     */
    public function __construct($file)
    {
        if (!file_exists($file)) {
            throw new Exception('Error : El archivo no pudo ser Encontrado');
        }
 
        $this->_file= $file;
        $ext        = substr(strrchr($file, '.'), 1);
 
        if (!isset($this->_tipoExcel[$ext])) {
            throw new Exception('Error : El archivo no es de un tipo Valido');
        }
        $this->_tipoPHPExcel    = $this->_tipoExcel[$ext];
 
    }
 
    /**
     * Carga la Hoja Excel y Retorna el Arreglo.
     * @param string $id    Contiene el nombre del encabezado que sera tomado como Id.
     *                      Si no se proporciona o no existe sera la primera columnas.
     * @return array
     */
    public function loadExcel($id = '')
    {
        $this->_createObjWorksheet();
        // Extraigo los Titulos
        for ($i=0; $i<= $this->_columnas-1; $i++) {
            $this->_titulos[$i] = $this->_objWorksheet->getCellByColumnAndRow($i, 1)->getCalculatedValue();
        }
        // Verifica el Campo Identificador
        $this->_id      = (in_array($id, $this->_titulos))? $id : $this->_titulos[0];
 
        // Levanto todos los Datos
        for ($fila = 2; $fila <= $this->_filas; $fila++) {
            $dFilas = array();
            for ($columna = 0; $columna <= $this->_columnas-1; $columna++) {
                $dFilas[$this->_titulos[$columna]] = 
                        $this->_objWorksheet->getCellByColumnAndRow($columna, $fila)->getCalculatedValue();
            }
            $this->_excel[$dFilas[$this->_id]] = $dFilas; 
        }
 
        return $this->_excel;
    }
 
    /**
     * Metodo Privado que crea el Objeto WorkSheet.
     * @return PHPExcel_Worksheet
     */
    private function _createObjWorksheet()
    {
 
        if (!$this->_objWorksheet instanceof  PHPExcel_Worksheet) {
            // Creo un objeto de Lectura con el tipo de Archivo Correcto Excel20007(xlsx), Excel5(xls)
            $objReader  = PHPExcel_IOFactory::createReader($this->_tipoPHPExcel);
            // Configuro que sera solo para leer el archivo
            $objReader	->setReadDataOnly(true);
            // Cargo el Archivo
            $objPHPExcel            = $objReader->load($this->_file);
            $this->_objWorksheet    = $objPHPExcel->getActiveSheet();
            $this->_columnas        = PHPExcel_Cell::columnIndexFromString($this->_objWorksheet->getHighestColumn());
            $this->_filas           = $this->_objWorksheet->getHighestRow();            
        } 
        return $this->_objWorksheet;
    }
 
    /**
     * Retorna el Campo seleccionado como Identificador.
     * @return string
     */
    public function getId()
    {
        return $this->_id;
    }
 
    /**
     * Retorna la Cantidad de Columnas del Archivo Excel.
     * @return integer
     */
    public function countColumns()
    {
        return $this->_columnas;
    }
 
    /**
     * Retorna la Cantidad de Filas del Archivo Excel.
     * @return integer
     */
    public function countRows()
    {
        return $this->_filas;
    }
 
    /**
     * Retorna si una Columna Existe o no.
     * @param   string  $nombreColumna  Nombre de la columna.
     * @return  boolean
     */
    public function isColumn($nombreColumna) 
    {
        return isset($this->_titulos[$nombreColumna]);
    }
 
    /**
     * Retorna el Arreglo Generado.
     * @return array
     */
    public function getArray()
    {
        return $this->_excel;
    }
 
    /**
     * Retorna los Titulos del Archivo Excel.
     * @return array
     */
    public function getTitulos()
    {
        return $this->_titulos;
    }
 
    /**
     * Retorna el registro para el id establecido.
     * @param   string  $id     Nombre del Identificador.
     * @return  array
     */
    public function findId($id)
    {
        $retorno    = false;
        if (isset($this->_excel[$id])) {
            $retorno = $this->_excel[$id];
        }
 
        return $retorno;
    }
 
    /**
     * Retorna un arreglo con el valor buscado en la columna indicada.
     * Busqueda Exacta.
     * @param   string  $titulo     Titulo de la Columna
     * @param   string  $valor      Valor a buscar
     * @return  array
     */
    public function findByColumn($titulo, $valor)
    {
       return $this->_search($this->_excel, $titulo, $valor);
    }
 
    /**
     * Extraida de :
     * @link http://php.net/manual/es/function.array-search.php
     */
    private function _search($array, $key, $value)
    {
        $results = array();
        if (is_array($array)) {
            if (isset($array[$key]) && $array[$key] == $value ) {
                $results[] = $array;
            }  
            foreach ($array as $subarray) {
                $results = array_merge($results, $this->_search($subarray, $key, $value));
            }  
        }
        return $results;
    }  
 
    /**
     * Retorna un arreglo con el valor buscado en la columna indicada o no y la cantidad 
     * de veces que aparece el valor en las columnas si no se indica la misma.
     * La busqueda es por valor aproximado.
     * @param   string  $buscar     Valor a Buscar
     * @param   string  $calve      Titulo de La columna donde se buscara o nada por Cualquiera.
     * @return  array
     */
    public function findByCount($buscar, $titulo = null) 
    {
        return $this->_recursiveArraySearchAll($this->_excel, $buscar, $titulo);
    }
 
    /**
     * Extraida de :
     * @link http://php.net/manual/es/function.array-search.php
     */        
    private function _recursiveArraySearchAll($haystack, $needle, $index = null)
    {
        $arrIterator    = new RecursiveArrayIterator($haystack);
        $recIterator    = new RecursiveIteratorIterator($arrIterator);
        $resultkeys     = array();
 
        while($recIterator->valid()) {
            if (!is_array($recIterator->current())) {
                if ((isset($index) AND $recIterator->key() == $index  AND strpos($recIterator->current(), $needle) !== false ) 
                    OR (!isset($index) AND strpos($recIterator->current(), $needle) !== false)) {
 
                    $resultkeys[$arrIterator->key()] = isset($resultkeys[$arrIterator->key()])?  $resultkeys[$arrIterator->key()] + 1 : 1;
                }
            }            
            $recIterator->next();
        }
        arsort($resultkeys);
        return $resultkeys;               
    }    
 
 
    /**
     * Metodo ordenar.
     * Ordena los resultados de acuerdo a la clave elegida.
     * @param   string  $clave  Clave por la cual se quiere ordenar(titulo de columna).
     * @param   boolean $asc    true para ascendente, false para descendente.
     * @return  array
     */
    public function sort($campo = 'name', $asc = true)
    {
        if (empty($this->_excel)) {
            throw new Exception('Primero debe usar la funcion loadExcel');
        }
        $arrSort    = $this->_excel;
 
        $ordenarPor = (in_array($campo, $this->_titulos))? $campo : $this->_id;
        $ascDesc    = ($asc)? SORT_ASC : SORT_DESC;
        $caracter   = 0;
 
        foreach ($arrSort as $ordenado) {
            $tmpArray[] = $ordenado[$ordenarPor];
            $caracter   = is_string($ordenado[$ordenarPor])? $caracter+1 : $caracter;
        }
 
        $numero     = ($caracter)? SORT_STRING : SORT_NUMERIC;
 
        array_multisort($tmpArray, $ascDesc, $numero, $arrSort);
        return $arrSort;
    } 
 
    /**
     * Retorna el Valor para una Celda Dada, buscando por el Array.
     * @param   string  $celda  Celda Excel tipo A1
     * @return  mixed   Valor de la Celda
     */
    public function getValueCellFromArray($celda)
    {
        $excelOriginal  = array_values($this->_excel);
        list($columna, $fila) = PHPExcel_Cell::coordinateFromString($celda);
        $columna        = PHPExcel_Cell::columnIndexFromString($columna);
 
        if ( ($fila) > $this->_filas || ($columna) > $this->_columnas ) {
            return null;
        }
 
        $retorno    = null;
        if ($fila == 1) {
            $retorno    = $this->_titulos[$columna - 1];
        } else {
            $excelOriginal  = array_values($excelOriginal[$fila - 2]);
            $retorno   = $excelOriginal[$columna - 1];
        }
       return $retorno ;
    }
 
    /**
     * Retorna el Valor de una Celda Especifica, sin tener que realizar la 
     * carga del Arreglo.
     * @param   string  $celda  Referencia de Celda tipo A1
     * @return  mixed
     */
    public function getValueCellFromExcel($celda)
    {
        list($columna, $fila) = PHPExcel_Cell::coordinateFromString($celda);
        $columna    = PHPExcel_Cell::columnIndexFromString($columna);
 
        return $this->_createObjWorksheet()->getCellByColumnAndRow($columna - 1, $fila)->getCalculatedValue();
    }
}

Bueno ahora veremos como se usa.

// En la Variable file ponemos direccion y nombre del Archivo a pasar a arreglo.
$file       = './claves_2.xlsx';
 
// Instanciamos la Clase y le pasamos la ruta y nombre del archivo
$buscador   = new ExcelToArray($file);
 
// Convertimos a un arreglo y le pasamos cual sera el titulo clave.
$buscador   ->loadExcel('usuario');
 
// Nos retorna el Arreglo del excel Completo
$arreglo      = $buscador->getArray();
 
// Busca una fila por la columna identificadora y retorna el un arreglo con clave y valor para cada una de las columnas
$users     = $buscador->findId('objetivophp');
 
// Ordena el Arreglo por una de las columnas y lo retorna
$arregloOrdenado = buscador->sort('usuario');
 
// Busqueda exacta por una columna determinada
// Retorna un arreglo para una fila pasando como parámetros un titulo y un valor 
$buscador->findByColumn('usuario', 'objetivophp');
 
// Buscar en cualquier columna cualquier valor que contenga 'obj'.
$buscador->findByCount('obj');
// Buscar en la columna usuario el usuario 'obj'
$buscador->findByCount('obj', 'usuario');

Todas los métodos retornan un arreglo.
El método findByCount, retorna un arreglo donde en la clave contiene el id de cada fila y en el valor la cantidad de columnas en la que aparece dicho valor.

Luego tenemos 2 métodos mas que buscan una celda especifica en el documento con la ubicacion de la celda tipo Excel. Ej.: A1, y retona el valor de dicha celda.
getValueCellFromArray y getValueCellFromExcel, como sus nombre lo indican retorna el valor desde el Excel mismo o del arreglo previamente cargado.

Lo ideal seria separar la clase en dos una que se encargue de la generación del arreglo del excel y otra clase que le pasemos el arreglo generado y se encargue de las búsquedas, así podríamos hacer que cada clase maneje una sola responsabilidad y hacerlas mas utilitarias.

Cualquier Consulta a las ordenes..
Saludos

Ahora ObjetivoPHP en Twitter

Ahora nos puedes seguir desde twitter, @objetivoPHP.

Saludos y espero que incremente la participación en el sitio.

Paginador en PHP versión 3.0.0

Bueno para no realizar otro articulo edito este y pongo la versión 3 del paginador, si bien se agrando un poco, tiene mayor flexibilidad y nuevas características. Dado que la explicación es extensa genere un archivo descargable con ejemplos y un pdf que nos muestra la configuración paso a paso.
La imagen siguiente muestra algunas de las barras de navegacion que se pueden obtener con esta clase y hojas de estilo.

Estilos de la barra de navegacion

Estilos para la barra de navegacion.

Espero que les sea de utilidad.
Paginador 3.0.0

Los estilos fueron obtenidos de los siguientes sitios.
Mis Algoritmos
TimerSys

Paginador en PHP versión 2.1.0

Bueno esta es una pequeña actualización de la clase paginador para ofrecer la funcionalidad de poder ocultar los mensajes de primero, anterior, siguiente, ultimo, bloque anterior, bloque siguiente etc que fue sugerido por el Usuario RAM, en el articulo de paginación. Como la sugerencia me pareció de utilidad y que aportaba facilidad para configurar la vista final que obtenemos versione la clase.
La forma de utilizar la clase es igual que la versión anterior (ver Paginador en PHP 2.0.0) lo único que incluimos un nuevo método llamado setOmitir($omitir = array) al cual se le pasara un arreglo con las etiquetas que no se quieren mostrar.

Ejemplo obtener que solo se muestren los enlaces siguiente y anterior.

    // Comenzamos con el paginador.
    require_once 'Paginador.php';
    // Instanciamos la clase Paginador
    $paginador          = new Paginador();
 
    // Configuramos cuanto registros por pagina que debe ser igual a el limit de la consulta mysql
    $paginador->setCantidadRegistros(1);
    $paginador->setCantidadEnlaces(1);
    $paginador->setOmitir(array('primero',
                                'numero',
                                'actual',
                                'bloqueAnterior',
                                'bloqueSiguiente',
                                'ultimo'));
    $paginador->setTitulosVista('anterior', '<< Anterior ');
    $paginador->setTitulosVista('siguiente', ' Siguiente >>');
 
    // Y mandamos a paginar desde la pagina actual y le pasamos tambien el total
    // de registros de la consulta mysql.
    $datos              = $paginador->paginar($pagina, $totalRegistros);
Es importante en este ejemplo configurar la cantidad de registros por pagina a 1, pues si solo queremos obtener algo del estilo <>, para que calcule bien el numero de paginas es importante que existe un solo registro por pagina. No es así con cantidad de enlaces porque por mas que fueran 5, 6 o 10 como no los mostrara para nosotros sera lo mismo en cuanto a la vista.
Algo a tener en cuenta que actual en caso de un enlace va a coincidir con numero, pero la diferencia es que si configuramos para no mostrar actual, entonces no se mostrara el enlace para la pagina en la cual estamos parados y el paginador podria mostrar algo como 1 2 4 5 6 … omitiría el 3 porque estamos en esa pagina.

Ahora el turno de la clase Paginador versionada.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
<?php
/**
 * Clase Paginador.
 * Su responsabilidad es realizarnos el paginado de una consulta, es decir
 * proporcionar datos para realizar la barra de navegacion de la paginacion.
 * @package     varias creado en el projecto opet
 * @copyright   2010 - ObjetivoPHP
 * @license     Gratuito (Free) http://www.opensource.org/licenses/gpl-license.html
 * @author      Marcelo Castro (ObjetivoPHP)
 * @link        objetivophp@*******.****
 * @version     2.1.0 (16/06/2008 - 09/04/2011)
 * @since       Version 2.1.0 agregado funcionalidad para omitir enlaces,
 *              idea de RAM.
 */
class Paginador
{
    /**
     * Contiene los titulos que se mostraran en la barra de navegacion. O sea
     * primera, anteriror, .... , ultima, siguiente etc...
     * @var array 
     */
    private $_titulos = array('primero'           => array('vista'  => '| Primero ...',
                                                           'title'  => 'Ir a la primera Pagina'),
                              'bloqueAnterior'    => array('vista'  => '<<',
                                                           'title'  => 'Bloque Anterior'),
                              'anterior'          => array('vista'  => '<',
                                                           'title'  => 'Pagina Anterior'),
                              'siguiente'         => array('vista'  => '>',
                                                           'title'  => 'Pagina Siguiente'),
                              'bloqueSiguiente'   => array('vista'  => '>>',
                                                           'title'  => 'Bloque Siguiente'),
                              'ultimo'            => array('vista'  => '... Ultimo |',
                                                           'title'  => 'Ir a la Ultima Pagina'),
                              'numero'            => array('vista'  => null,
                                                           'title'  => 'Ir a la pagina '),
                              'actual'            => array('vista'  => null,
                                                           'title'  => 'Estas viendo esta pagina')
                             );
 
    /**
     * Contiene los marcadores que van antes y despues de la pagina actual,
     * para identificarla visualmente en la barra de navegacion del paginador.
     * @var array
     */
    private $_marcador = array('antes'      => '|',
                               'despues'    => '|');
 
    /**
     * Guarda el resultado de la paginacion por si es requrido mas tarde.
     * Formato array('vista' => 'primero', 'numero' => 0).
     * @var array
     */
    private $_paginacion = array();
 
    /**
     * Es la cantidad de registros, filas de la tabla que se mostraran por cada
     * pantalla.
     * @var integer
     */
    private $_cantidadDeRegistrosPorPagina = 10;
 
    /**
     * Es la cantidad de Enlaces o vinculos que contendra el paginador, sin contar
     * los especiales como ser primero, ultimo etc..
     * @var integer
     */
    private $_cantidadDeEnlacesDelPaginador = 10;
 
    /**
     * Contiene la cantidad total de paginas del paginador.
     * @var integer
     */
    private $_cantidadPaginas;
 
    private $_omitir    = array();
 
    /**
     * Metodo __construct.
     * Crea el objeto Paginador.
     * @param   integer $crpp   Cantidad de Registros a desplegarse en cada Pagina.
     * @param   integer $cepp   Cantidad de enlaces del paginador, sin especiales.
     * @return  void
     */
    public function  __construct($crpp = 10, $cep = 10)
    {
        $this->_cantidadDeRegistrosPorPagina    = ((int)$crpp > 0)? $crpp : 10;
        $this->_cantidadDeEnlacesDelPaginador   = ((int)$cep > 0)? $cep : 10;
    }
 
    /**
     * Metodo setCantidadRegistros.
     * Configura la cantidad de registros que se desplegan en la pantalla.
     * @param   integer $cantidad   Cantidad de Registros por pagina.
     * @return  void
     */
    public function setCantidadRegistros($cantidad = 10)
    {
        $this->_cantidadDeRegistrosPorPagina    = ((int)$cantidad > 0)? $cantidad : 10;
    }
 
    /**
     * Metodo setCantidadEnlaces.
     * Configura la cantidad de enlaces que contendra el paginador sin considerar los
     * enlaces especiales.
     * @param   integer $cantidad   Cantidad de Enlaces que se quieren mostrar.
     * @return  void
     */
    public function setCantidadEnlaces($cantidad = 10)
    {
        $this->_cantidadDeEnlacesDelPaginador   = ((int)$cantidad > 0)? $cantidad : 10;
    }
 
    /**
     * Metodo paginar.
     * Realiza el paginado, generando todos los bloques.
     * @param   integer $pagina Contiene desde que pagina se desplegara.
     * @param   integer $cantidadDeResultados  total de resutados de la consulta.
     * @return  array
     */
	public function paginar($pagina,$cantidadDeResultados)
	{
        $pagina = ((int)$pagina < 0)? 0 : $pagina;
        if ($cantidadDeResultados < 1) { // No hay resultados que paginar
            return false;
        }
        // Aqui significa que tenemos resultados y vamos a paginar
        // Preparo las variables que se utilizaran
		$paginaInicial  = $paginaFinal    = 0;
		$paginacion     = array();
		$totalPaginas	= ceil($cantidadDeResultados / $this->_cantidadDeRegistrosPorPagina);
 
		if ($totalPaginas < 2) { // Si es menor a 2 es una pagina por lo tanto no pagino.
            $this->_cantidadPaginas = 1;
            return false;
        }
 
	   	if ($totalPaginas <= $this->_cantidadDeEnlacesDelPaginador) {
            $paginaInicial		= 1;
			$paginaFinal		= $totalPaginas;
		} else {
            $centroPaginador 	= floor($this->_cantidadDeEnlacesDelPaginador / 2);
			$paginaInicial		= ($pagina+1) - $centroPaginador;
			$paginaFinal		= $paginaInicial + $this->_cantidadDeEnlacesDelPaginador - 1;
 
			if ($paginaFinal > $totalPaginas) {
                $paginaFinal    = $totalPaginas;
				$paginaInicial  = $paginaFinal - ($this->_cantidadDeEnlacesDelPaginador -1);
			}
 
			if ($paginaInicial < 1) {
                $paginaInicial	= 1;
				$paginaFinal	= $this->_cantidadDeEnlacesDelPaginador;
			}
		}
 
		$ajuste				= floor($this->_cantidadDeEnlacesDelPaginador / 2);
		$ajuste2			= 1 - ($this->_cantidadDeEnlacesDelPaginador % 2);
		$blockInicio		= $paginaInicial - $this->_cantidadDeEnlacesDelPaginador + $ajuste  - 1;
		$blockFinal			= $paginaFinal + $this->_cantidadDeEnlacesDelPaginador - $ajuste  + $ajuste2;
 
		$paginaInicial		= $paginaInicial - 1;
		$paginaFinal		= $paginaFinal - 1;
 
		if ($totalPaginas > 1 && !in_array('primero', $this->_omitir)) {
            if ($paginaInicial != 0) {
                $paginacion[] = array('numero'   => 0,
                                      'vista'    => $this->_titulos['primero']['vista'],
                                      'title'    => $this->_titulos['primero']['title']);
            }
		}
		/* Configurar Block de Inicio */
		if ($blockInicio > $ajuste && !in_array('bloqueAnterior', $this->_omitir)) {
            $paginacion[]    = array('numero'    => $blockInicio,
                                     'vista'     => $this->_titulos['bloqueAnterior']['vista'],
                                     'title'     => $this->_titulos['bloqueAnterior']['title']);
        }
		/* Configurar anterior */
		if($pagina > 0 && !in_array('anterior', $this->_omitir)) {
            $paginacion[]    = array('numero'    => $pagina-1,
                                     'vista'     => $this->_titulos['anterior']['vista'],
                                     'title'     => $this->_titulos['anterior']['title']);
        }
		/* Inicio Block Central */
        for ( $f = $paginaInicial; $f <= $paginaFinal; $f++) {
            if ($f != $pagina && !in_array('numero', $this->_omitir)) {
                $paginacion[]= array('numero'    => $f,
                                     'vista'     => $f+1,
                                     'title'     => $this->_titulos['numero']['title'] . ($f+1));
            } elseif (!in_array('actual', $this->_omitir)) {
                $paginacion[]= array('numero'    => $f,
                                     'vista'     => $this->_marcador['antes']
                                                 . ($f+1) . $this->_marcador['despues'],
                                     'title'     => $this->_titulos['actual']['title']);
                }
            }
 
		/* Fin block Central */
		/* Configurar siguiente */
		if ($pagina < ($totalPaginas-1) && !in_array('siguiente', $this->_omitir)) {
            $paginacion[]    = array('numero'    => $pagina+1,
                                     'vista'     => $this->_titulos['siguiente']['vista'],
                                     'title'     => $this->_titulos['siguiente']['title']);
        }
		/* Fin block siguiente */
		/* Configurar Block de Final */
        if ($paginaFinal < ($totalPaginas - $this->_cantidadDeEnlacesDelPaginador - 1) && !in_array('bloqueSiguiente', $this->_omitir)) {
            $paginacion[]    = array('numero'    => $blockFinal-1,
                                     'vista'     => $this->_titulos['bloqueSiguiente']['vista'],
                                     'title'     => $this->_titulos['bloqueSiguiente']['title']);
        }
		/* Fin block Final */
		if ( $paginaFinal != ($totalPaginas - 1) && !in_array('ultimo', $this->_omitir)) {
            $paginacion[]    = array('numero'    => $totalPaginas-1,
                                     'vista'     => $this->_titulos['ultimo']['vista'],
                                     'title'     => $this->_titulos['ultimo']['title']);
		}
		$this->_paginacion      = $paginacion;
        $this->_cantidadPaginas = $totalPaginas;
		return $paginacion;
	}
 
    /**
     * Metodo setTitulosVista.
     * Configura los simbolos que se usaran para el enunciado de bloques,
     * primero, ultimo, anterior, siguiente etc...
     * @param   string  $titulo Titulo que se desea cambiar. primero, ultimo etc.
     * @param   string  $valor  Valor que tendra la etiqueta.
     * @return  void
     */
    public function setTitulosVista($titulo, $valor)
    {
        if (array_key_exists($titulo, $this->_titulos)) {
           $this->_titulos[$titulo]['vista'] = $valor;
        }
    }
 
    /**
     * Metodo setTitulosTitle.
     * @param   string  $titulo Etiqueta a la que se desea cambiar la propiedad title.
     * @param   string  $valor  Valor que tendra la etiqueta.
     * @return  void
     */
    public function setTitulosTitle($titulo, $valor)
    {
        if (array_key_exists($titulo, $this->_titulos)) {
           $this->_titulos[$titulo]['title'] = $valor;
        }
    }
 
    public function setOmitir($omitir = array())
    {
        if (is_array($omitir)) {
            $this->_omitir = $omitir;
        }
    }
 
    /**
     * Metodo setMarcador.
     * @param   string  $antes      Simbolo que va antes del enlace de pagina actual.
     * @param   string  $despues    Simbolo que va despues del enlace de la pagina actual.
     * @return  void
     */
    public function setMarcador($antes, $despues)
    {
        $this->_marcador['antes']   = $antes;
        $this->_marcador['despues'] = $despues;
    }
 
    /**
     * Metodo getPaginacion.
     * Nos retorna el arreglo de paginacion.
     * @return array
     */
    public function getPaginacion()
    {
        return $this->_paginacion;
    }
 
    /**
     * Metodo getCantidadPaginas.
     * Nos retorna la cantidad de paginas que tiene el paginador.
     * @return integer
     */
    public function getCantidadPaginas()
    {
        return $this->_cantidadPaginas;
    }
}
Bueno espero que esta pequeña modificación incremente la utilidad de la misma, saludos y gracias por los comentarios…