Pregunta

Considere el siguiente código y su salida:

Código

#!/usr/bin/perl -w
use strict;
use Data::Dumper;
my $HOURS_PER_DAY = 24.0 * 1.0;
my $BSA = 1.7 * 1.0;
my $MCG_PER_MG = 1000.0 * 1.0;
my $HOURS_DURATION    = 20.0 * $HOURS_PER_DAY;
my $dummy = $HOURS_PER_DAY * $BSA * $MCG_PER_MG * $HOURS_DURATION;
print Dumper($HOURS_PER_DAY);
print Dumper( $BSA);
print Dumper( $MCG_PER_MG);
print Dumper( $HOURS_DURATION );

Salida

$VAR1 = 24;
$VAR1 = '1.7';
$VAR1 = 1000;
$VAR1 = 480;

Como puede ver, la segunda variable se trata como cadenas, mientras que la primera y la cuarta se tratan como números. ¿Alguien tiene alguna idea de cuál es la lógica subyacente?

Editar los cálculos aritméticos que se agregaron no resuelven completamente el problema (vea la variable $ BSA).


$ 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
¿Fue útil?

Solución

Datos :: El trabajo de Dumper es serializar datos y no se puede decir mucho sobre lo que Perl está haciendo internamente con los datos en función de su salida. El módulo Devel :: Peek puede volcar los indicadores y valores subyacentes almacenados en las variables. El Devel :: Peek POD explica el significado de las banderas.

#!/usr/bin/perl

use warnings;
use strict;
use Devel::Peek;

my $HOURS_PER_DAY = 24.0 * 1.0;
my $BSA = 1.7 * 1.0;
my $MCG_PER_MG = 1000.0 * 1.0;
my $HOURS_DURATION    = 20.0 * $HOURS_PER_DAY;
my $dummy = $HOURS_PER_DAY * $BSA * $MCG_PER_MG * $HOURS_DURATION;

Dump($HOURS_PER_DAY);
Dump($BSA);
Dump($MCG_PER_MG);
Dump($HOURS_DURATION);

__END__
SV = PVNV(0xd71ff0) at 0xd87f90
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,NOK,pIOK,pNOK)
  IV = 24
  NV = 24
  PV = 0
SV = PVNV(0xd71fc8) at 0xd87f60
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,NOK,pIOK,pNOK)
  IV = 1
  NV = 1.7
  PV = 0
SV = PVNV(0xd72040) at 0xd87f40
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,NOK,pIOK,pNOK)
  IV = 1000
  NV = 1000
  PV = 0
SV = IV(0xd8b408) at 0xd87f30
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,pIOK)
  IV = 480
# compare the above output to output without the assignment to $dummy:
SV = IV(0x7b0eb8) at 0x7adf90
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,pIOK)
  IV = 24
SV = NV(0x7c7c90) at 0x7adf60
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,NOK,pNOK)
  NV = 1.7
SV = IV(0x7b13d8) at 0x7adf40
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,pIOK)
  IV = 1000
SV = IV(0x7b1408) at 0x7adf30
  REFCNT = 1
  FLAGS = (PADBUSY,PADMY,IOK,pIOK)
  IV = 480

Otros consejos

Todo su concepto de que Perl trata las variables como cadenas o números es defectuoso. Perl tratará sus variables de la manera correcta cuando lo necesite, por ejemplo, los operadores aritméticos siempre tratan sus argumentos como números (suponiendo que no está abusando de la sobrecarga de operadores o algo así).

No debe preocuparse por esto: Perl sabe lo que está haciendo.

Data :: Dumper está usando un patrón simple en la representación de cadena de la variable para determinar si es un número. Del código fuente:

...
elsif ($val =~ /^(?:0|-?[1-9]\d{0,8})\z/) { # safe decimal number
  $out .= $val;
}
else {               # string
...

Esto no coincide con los números que tienen un punto decimal que explica el comportamiento que observó.

Forma sucia rápida de forzar un contexto numérico:

print Dumper( $HOURS_DURATION + 0.0 );

Si su preocupación es cómo se mostrarán los datos, entonces la forma limpia es: -

printf "%5.2d",$HOURS_DURATION;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top