Подтвердить что ты не робот

Разница между $var = 500 и $var = '500'

В Perl, какая разница между

$status = 500;

и

$status = '500';
4b9b3361

Ответ 1

Не много. Они оба назначают пятьсот до $status. Используемый внутренний формат будет отличаться первоначально (IV vs PV, UTF8 = 0), но не имеет значения для Perl.

Тем не менее, есть вещи, которые ведут себя по-разному в зависимости от выбора формата хранения, хотя они и не должны. Основываясь на выборе формата хранения,

  • JSON решает, использовать ли кавычки или нет.
  • DBI угадывает тип SQL, который он должен использовать для параметра.
  • Побитовые операторы (&, | и ^) предполагают, являются ли их операнды строками или нет.
  • open и другие связанные с файлами встроенные имена кодируют имя файла с использованием UTF-8 или нет. (Ошибка!)
  • Некоторые математические операции возвращают отрицательный ноль или нет.

Ответ 2

Как уже @ikegami сказал не много. Но помните, что здесь МНОГО разница между

$ perl -E '$v=0500; say $v'

печатает 320 (десятичное значение для октавного номера 0500) и

$ perl -E '$v="0500"; say $v'

что печатает

0500

и

$ perl -E '$v=0900; say $v'

что умирает с ошибкой:

Illegal octal digit '9' at -e line 1, at end of line
Execution of -e aborted due to compilation errors.

и

perl -E '$v="0300";say $v+1'

печатает

301

но

perl -E '$v="0300";say ++$v'

печатает

0301

похож на 0x\d+, например:

$v = 0x900;
$v = "0x900";

Ответ 3

Существует только разница, если вы затем используете $var с одним из немногих операторов, которые имеют разные вкусы при работе с строкой или числом:

$string = '500';
$number = 500;
print $string & '000', "\n";
print $number & '000', "\n";

выход:

000
0

Ответ 4

Чтобы предоставить немного больше контекста для ответов "не так много", здесь представлено представление внутренних структур данных двух значений через модуль Devel:: Peek:

[email protected] ~ $ perl -MDevel::Peek -e 'print Dump 500; print Dump "500"'
SV = IV(0x7f8e8302c280) at 0x7f8e8302c288
  REFCNT = 1
  FLAGS = (PADTMP,IOK,READONLY,pIOK)
  IV = 500
SV = PV(0x7f8e83004e98) at 0x7f8e8302c2d0
  REFCNT = 1
  FLAGS = (PADTMP,POK,READONLY,pPOK)
  PV = 0x7f8e82c1b4e0 "500"\0
  CUR = 3
  LEN = 16

Вот дамп Perl, делающий то, что вы имеете в виду:

[email protected] ~ $ perl -MDevel::Peek -e 'print Dump ("500" + 1)'
SV = IV(0x7f88b202c268) at 0x7f88b202c270
  REFCNT = 1
  FLAGS = (PADTMP,IOK,READONLY,pIOK)
  IV = 501

Ответ 5

Первый - это число (целое число между 499 и 501). Вторая строка (символы "5", "0" и "0" ). Это не верно, что между ними нет никакой разницы. Это не верно, что он будет немедленно преобразован в другой. Он истинный, что строки при необходимости преобразуются в числа и наоборот, а преобразование в основном прозрачно, но не полностью.

Ответ Когда разница между строкой и числом в Perl 5 охватывает некоторые из случаев, когда они не эквивалентны:

  • Побитовые операторы обрабатывают численные номера численно (работают на битах двоичного представления каждого номера), но они обрабатывают строки по-разному (работают с битами каждого символа каждой строки).
  • Модуль JSON выводит строку в виде строки (с кавычками), даже если она числовая, но выводит число как число.
  • Очень маленькое или очень большое число может выглядеть иначе, чем вы ожидаете, в то время как строка уже является строкой и ее не нужно стягивать. То есть, если $x = 1000000000000000 и $y = "1000000000000000", то $x может привести к 1e+15. Поскольку использование переменной в качестве хеш-ключа является строкой, это означает, что $hash{$x} и $hash{$y} могут быть разными слотами хеша.
  • Команды smart-match (~~) и заданные/когда обрабатывают аргументы числа, отличные от числовых строк. Лучше всего избегать этих операторов.

Ответ 6

Существуют разные внутренние функции:)

($_ ^ $_) ne '0' ? print "$_ is string\n" : print "$_ is numeric\n" for (500, '500');

выход:

500 is numeric
500 is string

Ответ 7

Я думаю, это прекрасно демонстрирует, что происходит.

$ perl -MDevel::Peek -e 'my ($a, $b) = (500, "500");print Dump $a; print Dump $b; $a.""; $b+0; print Dump $a; print Dump $b'
SV = IV(0x8cca90) at 0x8ccaa0
  REFCNT = 1
  FLAGS = (PADMY,IOK,pIOK)
  IV = 500
SV = PV(0x8acc20) at 0x8ccad0
  REFCNT = 1
  FLAGS = (PADMY,POK,pPOK)
  PV = 0x8c5da0 "500"\0
  CUR = 3
  LEN = 16
SV = PVIV(0x8c0f88) at 0x8ccaa0
  REFCNT = 1
  FLAGS = (PADMY,IOK,POK,pIOK,pPOK)
  IV = 500
  PV = 0x8d3660 "500"\0
  CUR = 3
  LEN = 16
SV = PVIV(0x8c0fa0) at 0x8ccad0
  REFCNT = 1
  FLAGS = (PADMY,IOK,POK,pIOK,pPOK)
  IV = 500
  PV = 0x8c5da0 "500"\0
  CUR = 3
  LEN = 16

Каждый скаляр (SV) может иметь представление строки (PV) и числовое (IV). Как только вы используете переменную с только строковым представлением в любой числовой операции и одну с только числовым представлением в любой строковой операции, у них есть оба представления. Верно, может быть и другое числовое представление, представление с плавающей запятой (NV), поэтому существует три возможных представления скалярного значения.

Ответ 8

Много ответов уже на этот вопрос, но я дам ему шанс для путаного новичка:

my $foo = 500;
my $bar = '500';

Как и они, для практических размывов они являются "одинаковыми". Интересная часть - когда вы используете операторов. Например:

print $foo + 0;

output: 500

Оператор "+" видит число слева и число справа, оба десятичного знака, поэтому ответ равен 500 + 0 = > 500

print $bar + 0;

output: 500

В том же выводе оператор видит строку, которая выглядит как десятичное целое слева, а справа - нуль, поэтому 500 + 0 = > 500

Но где различия? Это зависит от используемого оператора. Операторы решают, что произойдет. Например:

my $foo = '128hello';
print $foo + 0;
output: 128

В этом случае он ведет себя как atoi() в C. Он берет большую числовую часть, начиная с левой и использует ее как число. Если номеров нет, он использует их как 0.

Как справиться с этим в условных выражениях?

my $foo = '0900';
my $bar = 900;
if( $foo == $bar)
{print "ok!"}
else
{print "not ok!"}

output: ok!

== сравнивает численное значение в обеих переменных. если вы используете предупреждения, он будет жаловаться на использование == со строками, но он все равно попытается принудить.

my $foo = '0900';
my $bar = 900;
if( $foo eq $bar)
{print "ok!"}
else
{print "not ok!"}

output: not ok!

eq сравнивает строки для равенства.

Ответ 9

Вы можете попробовать оператор "^".

my $str  = '500';
my $num  = 500;

if ($num ^ $num)
{
    print 'haha\n';
}

if ($str ^ $str)
{
    print 'hehe\n';
}

$str ^ $str отличается от $num ^ $num, поэтому вы получите "хе-хе". ps, "^" изменят аргументы, поэтому вы должны сделать

my $temp = $str;
if ($temp ^ $temp )
{
    print 'hehe\n';
}

. Я обычно использую этот оператор, чтобы рассказать разницу между num и str в perl.