Pregunta

Considere lo siguiente:

print 3 ** 333; #Yields 7.6098802313206e+158

Mi pregunta es simple: ¿cómo puedo desactivar la notación científica cuando trabajo con números muy grandes? Básicamente, me gustaría ver todos los dígitos volcados a stdout textualmente.

¿Es esto posible?

¿Fue útil?

Solución

Ver Math::BigInt

use Math::BigInt;
$x = Math::BigInt->new("3");
print $x ** 333;

Salida:

760988023132059809720425867265032780727896356372077865117010037035791631439306199613044145649378522557935351570949952010001833769302566531786879537190794573523

Otros consejos

Si desea hacerlo para todos los enteros en su programa, simplemente puede agregar:

use bigint;

Si solo desea hacerlo para algunos enteros, puede crear Math :: BigInt objetos.

También hay bignum y Math :: BigNum si está trabajando con flotantes.

Para valores muy pequeños vea el siguiente código:

my $value = 1e-07;                 # = 0.0000001

# NOPE

print $value;                      # prints 1e-07, $value is a number
print sprintf("%f", $value);       # prints 0, $value is a number
print sprintf("%.10f", $value);    # prints 0.0000001000, $value is a number
$value = sprintf("%.10f", $value);
print $value                       # prints 1e-07, $value is a number

# /NOPE

use bignum;
$value = ($value+0)->bstr();
print $value;                      # prints 0.0000001, $value is a string
no bignum;
print $value;                      # prints 0.0000001, $value is a string

# HOORAY

Con números tan grandes puede tener más dígitos que la precisión utilizada para almacenar los números. (Ver un ejemplo ejecutable simple habría resuelto esta pregunta).

Si realmente necesita ver más de 150 dígitos, debe usar los módulos bigint (para enteros), bigrat (para números racionales) y bignum (para números de coma flotante).

Tuve el mismo problema con este código:

#!/usr/bin/perl
use strict;
use warnings;
print "Base Exp    MAX Signed-Negitive     MAX Signed-Positive            MAX Unsigned\n";
for( my $x = 1; $x <= 64; $x++ ) {
    my $y = (2 ** $x);
    printf( "2 ^ %4d = %20d to %-20d or %20d\n",
                 $x,   $y/-2,  $y/2,    $y );
}

Las dos últimas líneas donde se imprime:

2 ^   63 = -4611686018427387904 to 4611686018427387904  or -9223372036854775808
2 ^   64 = -9223372036854775808 to -9223372036854775808 or                   -1

Obviamente no está bien, y al no darme cuenta de que la conversión% d estaba causando el problema, probé la solución marcada aquí:

#!/usr/bin/perl
use strict;
use warnings;
use Math::BigInt;
print "Base Exp    MAX Signed-Negitive     MAX Signed-Positive            MAX Unsigned\n";
for( my $x = Math::BigInt->new('1'); $x <= 64; $x++ ) {
    my $y = Math::BigInt->new(2 ** $x);
    printf( "2 ^ %4d = %20d to %-20d or %20d\n",
                 $x,   $y/-2,  $y/2,    $y );
}

Fue entonces cuando me di cuenta de que la conversión printf 'd' estaba causando un problema. Leer sobre Math :: BigInt parece sugerir que estos números se almacenan como cadenas dentro, por lo que al cambiar a una conversión 's', se solucionó el problema:

#!/usr/bin/perl
use strict;
use warnings;
use Math::BigInt;
print "Base Exp    MAX Signed-Negitive     MAX Signed-Positive            MAX Unsigned\n";
for( my $x = Math::BigInt->new('1'); $x <= 64; $x++ ) {
    my $y = Math::BigInt->new(2 ** $x);
    printf( "2 ^ %4s = %20s to %-20s or %20s\n",
                 $x,   $y/-2,  $y/2,    $y );
}

Ahora las dos últimas líneas impresas correctamente:

2 ^   63 = -4611686018427387904 to 4611686018427387904  or  9223372036854775808
2 ^   64 = -9223372036854775808 to 9223372036854775808  or 18446744073709551616

Pero en lo que respecta a la respuesta de Karel, que era casi correcta en mi humilde opinión, esto también podría hacerse sin el uso de BigInt (bigint, BigNum, ...) utilizando la conversión 'f' pero con la precisión establecida en '0 'para eliminar esos decimales:

#!/usr/bin/perl
use strict;
use warnings;
print "Base Exp    MAX Signed-Negitive     MAX Signed-Positive            MAX Unsigned\n";
for( my $x = 1; $x <= 64; $x++ ) {
    my $y = (2 ** $x);
    printf( "2 ^ %4d = %20.0f to %-20.0f or %20.0f\n",
                 $x,   $y/-2,  $y/2,    $y );
}

Esto también funciona para la pregunta del OP:

perl -e 'printf "%.0f\n", 3 ** 333'
760988023132059813486251563646478824265752535077884574263917414498578085812167738721447369281049109603746001743233145041176969930222526036520619613114171654144
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top