Pregunta

En una plataforma Windows de 32 bits, tengo que leer algunos números que, esto fue inesperado, pueden tener valores tan grandes como 99,999,999,999, pero no más. Intentando sprintf ("% 011d " ;, $ myNum) ellos genera un desbordamiento: -2147483648.

No puedo usar el módulo BigInt porque en este caso debería cambiar profundamente el código. No puedo administrar el formato como cadena, sprintf ("% 011s " ;, $ numero) , porque el signo menos se maneja incorrectamente.

¿Cómo puedo manejar esto? ¿Podría empacar / desempaquetar algo de ayuda?

¿Fue útil?

Solución

Intente formatearlo como flotante sin parte de fracción:

$ perl -v
This is perl, v5.6.1 built for sun4-solaris
...

$ perl -e 'printf "%011d\n", 99999999999'
-0000000001

$ perl -e 'printf "%011.0f\n", 99999999999'
99999999999

Otros consejos

Sí, uno de los puntos ciegos numéricos de Perl es el formateo; Perl maneja automáticamente la representación de números como enteros o flotantes bastante bien, pero luego los obliga a uno u otro cuando se utilizan los formatos numéricos printf , incluso cuando eso no es apropiado. Y printf realmente no maneja BigInts en absoluto (excepto tratando ellos como cadenas y convirtiéndolo en un número, con pérdida de precisión).

Usar% s en lugar de% d con cualquier número que no esté seguro estará en un lugar apropiado El rango es una buena solución alternativa, excepto cuando tenga en cuenta los números negativos. Manejar esos, vas a tener que escribir un código Perl.

No soy un experto en Perl, y tal vez me estoy perdiendo algún tipo de manejo automático de bignums aquí, pero ¿no es esto simplemente un caso de desbordamiento de enteros? Un entero de 32 bits no puede contener números tan grandes como 99,999,999,999.

De todos modos, obtengo el mismo resultado con Perl v5.8.8 en mi máquina Linux de 32 bits, y parece que printf con &%;% d " no maneja números más grandes.

Creo que su copia de Perl debe estar rota, esto es de la versión de CygWin (5.10):

pax$ perl -e 'printf("%011d\n", 99999999999);'
99999999999

pax$ perl -v

This is perl, v5.10.0 built for cygwin-thread-multi-64int
(with 6 registered patches, see perl -V for more detail)

Copyright 1987-2007, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

¿Qué versión está ejecutando (salida de perl -v )?

Es posible que deba obtener una versión habilitada de 64 bits de Perl [y posiblemente una nueva máquina de producción de 64 bits] (observe el " cygwin-thread-multi-64int " en mi salida ) Eso al menos evitará la necesidad de cambiar el código.

Estoy afirmando esto sobre la base de que no quieres cambiar mucho el código (es decir, temes romper cosas). La solución del nuevo hardware, aunque es un poco cara, casi seguramente no requerirá que cambie el software en absoluto . Depende de tus prioridades.

Otra posibilidad es que Perl mismo pueda estar almacenando el número correctamente pero simplemente mostrándolo incorrectamente debido a una falla printf () . En ese caso, puede intentar:

$million = 1000000;
$bignum = 99999999999;
$firstbit = int($bignum / $million);
$secondbit = $bignum - $firstbit * million;
printf ("%d%06d\n",$firstbit,$secondbit);

Ponga eso en una función y llame a la función para devolver una cadena, como:

sub big_honkin_number($) {
    $million = 1_000_000;
    $bignum = shift;
    $firstbit = int($bignum / $million);
    $secondbit = $bignum - $firstbit * $million;
    return sprintf("%d%06d\n", $firstbit, $secondbit);
}
printf ("%s", big_honkin_number (99_999_999_999));

Tenga en cuenta que probé esto, pero en la plataforma de 64 bits: deberá hacer su propia prueba en 32 bits, pero puede usar el factor de escala que desee (incluyendo más de dos segmentos si es necesario).

Actualización: Ese truco big_honkin_number () funciona bien en un Perl de 32 bits, por lo que parece que es solo el funciones printf () que te están llenando:

pax@pax-desktop:~$ perl -v

This is perl, v5.8.8 built for i486-linux-gnu-thread-multi

Copyright 1987-2006, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

pax@pax-desktop:~$ perl qq.pl
99999999999
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top