Різниця між $ var = 500 і $ var = '500'

У Perl, яка різниця між ними

$status = 500;

і

$status = '500';
28
Якщо статус є числовим, призначте номер. Якщо це рядок, призначте рядок. Зверніть увагу, що рядок, що складається тільки з цифр, не обов'язково є числовою кількістю (як у "номері соціального забезпечення").
додано Автор Ingo, джерело
додано Автор Ilmari Karonen, джерело

21 Відповіді

Не багато. Обидва вони призначають п'ять сотень до $ status . Внутрішній формат, що використовується, буде спочатку іншим (IV проти PV, UTF8 = 0), але це не має значення для Perl.

Однак є речі, які ведуть себе по-різному залежно від вибору формату зберігання, навіть якщо вони не повинні. Виходячи з вибору формату зберігання,

  • JSON decides whether to use quotes or not.
  • DBI guesses the SQL type it should use for a parameter.
  • The bitwise operators (&, | and ^) guess whether their operands are strings or not.
  • open and other file-related builtins encode the file name using UTF-8 or not. (Bug!)
  • Some mathematical operations return negative zero or not.
39
додано
@alexk, див. оновлення.
додано Автор ikegami, джерело
Якщо ви передаєте цей номер через конструктор JSON, то виведете "500", інший виведе 500
додано Автор alexk, джерело

Як вже @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";
21
додано
Awesome відповідь я буду зберігати в моїй Perl подробиці & thingies папку
додано Автор ado, джерело
@ jm666 Також 4 + 4 відрізняється від '4 + 4' . Це викликає багато питань у питаннях інтерполяції.
додано Автор ikegami, джерело
@cajwine, Ви говорите, що ви не хочете знати внутрішні деталі. Я повністю з цим погоджуюсь, тому я не пішов у них. Але тоді ви скаржилися, що я не вдавався в подробиці про внутрішні органи? Я згадав саме те, що вам потрібно, щоб подивитися, якщо ви хочете зануритися в кишки. Ви шукали IV і PV? illguts - це добре прочитане.
додано Автор ikegami, джерело
@cajwine, Ні, моя відповідь не полягає в тому, що X та Y є одночасно вуглецевими (коли було б корисніше сказати, що вони алмази та графіт); Моя відповідь полягає в тому, що Х і Y є обома алмазами (п'ятсот). Один з південної сторони шахти; інший на північ, але ніхто не піклується. Ви, здається, неправильно зрозуміли мою відповідь.
додано Автор ikegami, джерело
Будь ласка, не запускайте жодного вогню. (Мій перл знання - це лише частина знань (і інших) Ікегамі - тільки намагався допомогти з мого "рівня".
додано Автор jm666, джерело
Це здається трохи нерелевантним до питання, яке буде вибрано як відповідь IMO
додано Автор plusplus, джерело
@cajwine - моя точка зору не мала нічого спільного з рівнями відповідей, тільки те, що початок говорити про вісімкові числа, не було найбільш корисним для питання, яке досить чітко запитує про різницю між 500 та <�кодом > "500" . Відповідь залишається цікавою та корисною, а також бажаним доповненням до дискусії, але просто не повинна бути вибраною відповіддю, тому що вона не відповідає на питання ОП.
додано Автор plusplus, джерело

Існує лише різниця, якщо ви використовуєте $ var з одним з небагатьох операторів, які мають різні смаки під час роботи з рядком або номером:

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

вихід:

000
0
19
додано
Це, здається, найбільш практична відповідь для мене.
додано Автор matt freake, джерело

Існує лише різниця, якщо ви використовуєте $ var з одним з небагатьох операторів, які мають різні смаки під час роботи з рядком або номером:

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

вихід:

000
0
19
додано
Це, здається, найбільш практична відповідь для мене.
додано Автор matt freake, джерело

Існує лише різниця, якщо ви використовуєте $ var з одним з небагатьох операторів, які мають різні смаки під час роботи з рядком або номером:

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

вихід:

000
0
19
додано
Це, здається, найбільш практична відповідь для мене.
додано Автор matt freake, джерело

Щоб надати дещо більше контексту "не багато" відповідей, тут представлено внутрішні структури даних двох значень через модуль 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
8
додано

Щоб надати дещо більше контексту "не багато" відповідей, тут представлено внутрішні структури даних двох значень через модуль 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
8
додано

Щоб надати дещо більше контексту "не багато" відповідей, тут представлено внутрішні структури даних двох значень через модуль 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
8
додано

Перший - це число (ціле число між 499 і 501). Другий - рядок (символи '5', '0', '0'). Це не вірно , що між ними немає різниці. Це не вірно , що буде негайно перетворено на інше. Це є вірно, що рядки перетворюються в числа, коли це необхідно, і навпаки, і перетворення в основному прозоре, але не повністю.

Відповідь Коли різниця між рядком і числом у Perl 5 охоплює деякі з випадків, коли вони не еквівалентні:

  • Побітові оператори обробляють числа чисельно (працюють на бітах двійкового представлення кожного числа), але вони обробляють рядки символом (діючи на біти кожного символу кожної рядки).
  • Модуль JSON виводить рядок у вигляді рядка (з лапками), навіть якщо він є числовим, але виводить номер як число.
  • Дуже маленьке чи дуже велике число може бути різним, ніж ви очікуєте, тоді як рядок вже є рядком і не потребує підстановки. Тобто, якщо $ x = 1000000000000000 і $ y = "1000000000000000" , то $ x може вказати 1e + 15 . Оскільки використання змінної як хеш-ключа є строгою, це означає, що $ hash {$ x} та $ hash {$ y} можуть бути різними хеш-слотами.
  • Smart-match ( ~~ ) і заданий /, коли оператори відносяться до числових аргументів по-різному від числових рядків. Найкраще уникати цих операторів.
6
додано

Перший - це число (ціле число між 499 і 501). Другий - рядок (символи '5', '0', '0'). Це не вірно , що між ними немає різниці. Це не вірно , що буде негайно перетворено на інше. Це є вірно, що рядки перетворюються в числа, коли це необхідно, і навпаки, і перетворення в основному прозоре, але не повністю.

Відповідь Коли різниця між рядком і числом у Perl 5 охоплює деякі з випадків, коли вони не еквівалентні:

  • Побітові оператори обробляють числа чисельно (працюють на бітах двійкового представлення кожного числа), але вони обробляють рядки символом (діючи на біти кожного символу кожної рядки).
  • Модуль JSON виводить рядок у вигляді рядка (з лапками), навіть якщо він є числовим, але виводить номер як число.
  • Дуже маленьке чи дуже велике число може бути різним, ніж ви очікуєте, тоді як рядок вже є рядком і не потребує підстановки. Тобто, якщо $ x = 1000000000000000 і $ y = "1000000000000000" , то $ x може вказати 1e + 15 . Оскільки використання змінної як хеш-ключа є строгою, це означає, що $ hash {$ x} та $ hash {$ y} можуть бути різними хеш-слотами.
  • Smart-match ( ~~ ) і заданий /, коли оператори відносяться до числових аргументів по-різному від числових рядків. Найкраще уникати цих операторів.
6
додано

Перший - це число (ціле число між 499 і 501). Другий - рядок (символи '5', '0', '0'). Це не вірно , що між ними немає різниці. Це не вірно , що буде негайно перетворено на інше. Це є вірно, що рядки перетворюються в числа, коли це необхідно, і навпаки, і перетворення в основному прозоре, але не повністю.

Відповідь Коли різниця між рядком і числом у Perl 5 охоплює деякі з випадків, коли вони не еквівалентні:

  • Побітові оператори обробляють числа чисельно (працюють на бітах двійкового представлення кожного числа), але вони обробляють рядки символом (діючи на біти кожного символу кожної рядки).
  • Модуль JSON виводить рядок у вигляді рядка (з лапками), навіть якщо він є числовим, але виводить номер як число.
  • Дуже маленьке чи дуже велике число може бути різним, ніж ви очікуєте, тоді як рядок вже є рядком і не потребує підстановки. Тобто, якщо $ x = 1000000000000000 і $ y = "1000000000000000" , то $ x може вказати 1e + 15 . Оскільки використання змінної як хеш-ключа є строгою, це означає, що $ hash {$ x} та $ hash {$ y} можуть бути різними хеш-слотами.
  • Smart-match ( ~~ ) і заданий /, коли оператори відносяться до числових аргументів по-різному від числових рядків. Найкраще уникати цих операторів.
6
додано

Думаю, це чудово демонструє те, що відбувається.

$ 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 ), так що є три можливих представлення скалярного значення.

3
додано

Думаю, це чудово демонструє те, що відбувається.

$ 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 ), так що є три можливих представлення скалярного значення.

3
додано

Існують різні внутрішньо :)

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

вихід:

500 is numeric
500 is string
3
додано

Існують різні внутрішньо :)

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

вихід:

500 is numeric
500 is string
3
додано

Існують різні внутрішньо :)

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

вихід:

500 is numeric
500 is string
3
додано

Багато відповідей вже на це запитання, але я дам йому постріл для путаного новачка

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

Як вони є, для практичних прикладів вони є "однаковими". Цікава частина, коли ви використовуєте операторів. Наприклад:

print $foo + 0;

output: 500

The '+' operator sees a number at its left and a number at its right, both decimals, hence the answer is 500 + 0 => 500

print $bar + 0;

output: 500

Same output, the operator sees a string that looks like a decimal integer at its left, and a zero at its right, hence 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 порівнює рядки для рівності.

2
додано

Багато відповідей вже на це запитання, але я дам йому постріл для путаного новачка

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

Як вони є, для практичних прикладів вони є "однаковими". Цікава частина, коли ви використовуєте операторів. Наприклад:

print $foo + 0;

output: 500

The '+' operator sees a number at its left and a number at its right, both decimals, hence the answer is 500 + 0 => 500

print $bar + 0;

output: 500

Same output, the operator sees a string that looks like a decimal integer at its left, and a zero at its right, hence 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 порівнює рядки для рівності.

2
додано

Ви можете спробувати оператора "^".

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

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

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

$ str ^ $ str відрізняється від $ num ^ $ num, тому ви отримаєте "hehe". ps, "^" змінить аргументи, так що ви повинні робити

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

. Зазвичай я використовую цей оператор, щоб визначити різницю між num та str в perl.

0
додано

Ви можете спробувати оператора "^".

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

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

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

$ str ^ $ str відрізняється від $ num ^ $ num, тому ви отримаєте "hehe". ps, "^" змінить аргументи, так що ви повинні робити

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

. Зазвичай я використовую цей оператор, щоб визначити різницю між num та str в perl.

0
додано

Ви можете спробувати оператора "^".

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

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

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

$ str ^ $ str відрізняється від $ num ^ $ num, тому ви отримаєте "hehe". ps, "^" змінить аргументи, так що ви повинні робити

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

. Зазвичай я використовую цей оператор, щоб визначити різницю між num та str в perl.

0
додано