Página 1 de 1

Error módulo Lingua::ES::Numeros

NotaPublicado: 2010-01-04 09:15 @427
por Lor
Explorer, he detectado un error en el módulo Lingua::ES::Numeros;

Dado el número 62.482,50

my $letras = Lingua::ES::Numeros->new('MAYUSCULAS' => 1);
$letras->real(62.482,50);

Da como resultado: SESENTA Y DOS MIL CUATROCIENTOS OCHENTA Y DOS CON 05 CTMS

¿Cómo se notifica el mismo para corrección?

Re: Error módulo Lingua::ES::Numeros

NotaPublicado: 2010-01-04 10:52 @494
por explorer
Lo normal es escribir un correo a la dirección de correo que figura al final del módulo (la dirección de cpan.org).

Si al cabo de un par de días no te responde, lo siguiente es enviar un mensaje de error en la página de seguimiento de incidencias del propio módulo.

Y al mismo tiempo, le intentas localizar en Internet. En este caso, tiene página en Twitter y un Blog llamada Perliscopio.

Es un error grave... yo intentaría mandarle un aviso a todos los sitios, a la vez.

Mientras, voy a ver dónde está el problema.

Re: Error módulo Lingua::ES::Numeros

NotaPublicado: 2010-01-05 22:41 @987
por explorer
Bueno, después de una breve investigación, he llegado a los siguientes puntos:

* El error se mantiene incluso en la última versión (0.06).

* He conseguido realizar un apaño, que parece que funciona. Explicado más abajo.

* Los más de 70.000 test que pasa el módulo antes de su instalación, no lo detecta (!)

El tema está en la función real(), que sirve para formatear los números a una determinada precisión en los decimales. Para ello, se hace uso del atributo FORMATO que por defecto es 'con %02d ctms.'. Hay dos formas de indicar esa precisión:
1- %Ns: la parte fraccionaria se pasa a cardinal con la precisión de decimales indicada con N. Por ejemplo: si es FORMATO => 'con %2s ctms.', saldría algo como 'CINCO DÉCIMOS CTMS.'
2- %Nd: la parte fraccionaria se pasa a número, como en la función sprintf()

Y ahí es donde creo que está el error:

En la función real() aparece:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.              # Numérico, se da formato a los dígitos
  2.              $frc = substr( '0' x $exp . $frc, 0, $1 );
  3.              $frc = sprintf( $self->{'FORMATO'}, $frc );
  4.              last;
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

Observamos que la parte fraccionaria se rellena con ceros por la parte derecha según lo indique el exponente del número. Luego, se extraen tantos dígitos como lo indique la precisión asignada a FORMATO. Pasa luego el número por la función sprintf con el formato indicado, y termina.

El problema es que del número de ejemplo "62482.50", la parte fraccionaria queda en "5", debido a que Perl elimina el '0' final (los ceros a la derecha no tienen "valor"). Esto es así porque estamos pasando un número a una función, y Perl hace el "redondeo" numérico antes de agregarlo como argumento a la función. Más tarde, las rutinas de parseo del módulo lo siguen manteniendo así, hasta que llega a la parte de formateo de la expresión indicada antes.

La solución que he encontrado es "agregar" los ceros eliminados a la derecha, tantos como los indicados en la expresión de formato (al menos). Para ello, modifiqué la línea 331 de la siguiente manera:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.              # Numérico, se da formato a los dígitos
  2.              $frc = substr( '0' x $exp . $frc . '0' x $1, 0, $1 );
  3.              $frc = sprintf( $self->{'FORMATO'}, $frc );
  4.              last;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

y ya sale la respuesta correcta:
SESENTA Y DOS MIL CUATROCIENTOS OCHENTA Y DOS CON 50 CTMS.

Haciendo una prueba con otro formato,
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. use utf8;
  7. use open IO  => ':locale';
  8.  
  9. use Lingua::ES::Numeros;
  10.  
  11. my $letras = Lingua::ES::Numeros->new('MAYUSCULAS' => 1, FORMATO => 'con %3d milésimas');
  12.  
  13. print $letras->real(62482.50), "\n"; # SESENTA Y DOS MIL CUATROCIENTOS OCHENTA Y DOS CON 500 MILÉSIMAS
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Y vemos que funciona: la parte fraccionaria es "rellenada" con ceros a la derecha.

No sé si es la solución correcta, pero al menos, parece que funciona.

Ahora bien... alguien podría pensar que hay una solución más sencilla... en vez de
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. print $letras->real(62482.50), "\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
podríamos indicarlo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. print $letras->real("62482.50"), "\n"; # SESENTA Y DOS MIL CUATROCIENTOS OCHENTA Y DOS CON 50 CTM.
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
y de esa manera, el '0' final no es descartado al no haber una conversión a número, sino que estamos pasando una cadena de caracteres. Y es cierto, la salida sale bien. Pero... tenemos que modificar el programa para acordarnos de que siempre deben aparecer dos dígitos en la parte fraccionaria, porque sino,
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. print $letras->real("62482.5"), "\n"; # SESENTA Y DOS MIL CUATROCIENTOS OCHENTA Y DOS CON  5 CTM.
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
fallará.

Ahora intento comunicarme con el autor para decírselo.

Actualización
El ejemplo completo que pone Lor es 62.482,50.

Aquí tenemos otro problema: la notación que por defecto está esperando Perl es la anglosajona (el punto como separador decimal). Así que lo que tenemos que hacer es decirle al objeto del módulo cómo son los números que queremos procesar:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. use utf8;
  7. use open IO  => ':locale';
  8.  
  9. use Lingua::ES::Numeros;
  10.  
  11. my $letras = Lingua::ES::Numeros->new(
  12.     MAYUSCULAS =>   1,
  13.     DECIMAL     => ',',
  14.     SEPARADORES => '.',
  15. );
  16.  
  17. print $letras->real("62.482,50"), "\n"; # SESENTA Y DOS MIL CUATROCIENTOS OCHENTA Y DOS CON 50 CTMS.
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Sólo hemos agregado DECIMAL y SEPARADORES, y ahora ya obtenemos la salida esperada.

Re: Error módulo Lingua::ES::Numeros

NotaPublicado: 2010-01-06 05:37 @276
por Lor
¡¡¡¡¡Grande Explorer!!!!!

He enviado un email a José Rey pero no he tenido respuesta.

He reportado el error enviando un email a [email protected]

¡¡¡Gracias!!! :D

Re: Error módulo Lingua::ES::Numeros

NotaPublicado: 2010-01-06 05:55 @288
por Lor
Por lo que veo ya se hizo la corrección. Ahora tenemos la versión v0.07

Explorer, ¡¡¡Gracias por todo!!!

Re: Error módulo Lingua::ES::Numeros

NotaPublicado: 2010-01-06 14:38 @651
por explorer
José me ha respondido por correo. En dos horas preparó el arreglo y lo subió a CPAN.

Voy a bajar esa versión y ver qué es lo que ha tocado (por insaciable curiosidad, claro).

Actualización:
Estas son las diferencias que ha puesto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
casa:/usr/lib/perl5/site_perl/5.8.8/Lingua/ES # diff Numeros.pm*
42c42
< our $VERSION = '0.07';
---
> our $VERSION = '0.06';
331c331
<             $frc = substr( '0' x $exp . $frc . '0' x $1, 0, $1 );
---
>             $frc = substr( '0' x $exp . $frc, 0, $1 );
691,698d690
<
<     # Translate the lower 6 digits for female numbers
<     if ($gen eq FEMALE) {
<         $n =~ s/(.{1,6})$//x;
<         $fmag->( $1, \@group, $mag++ );
<         s/cientos$/cientas/g for @group;
<     }
<
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Vemos que ha admitido mi solución, y ha agregado un formateo para los números menores de un millón, en femenino.

¡Vaya!
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Revision history for Perl extension Lingua::ES::Numeros.

0.07  Wed Jan  6 00:14:36 VET 2010
    - Corrected fractional formating bug in real() thanks to Joaquin Ferrero
    - Corrected female hundreths under one million
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Un bonito regalo de Rey(es) :D

Re: Error módulo Lingua::ES::Numeros

NotaPublicado: 2010-01-06 15:11 @674
por Lor
!!!!FELICITACIONES!!!!!