Jak przekonwertować ciąg znaków na liczbę w Perlu?

86

Mam ciąg, który zawiera wartość dziesiętną i muszę przekonwertować ten ciąg na zmienną zmiennoprzecinkową. Tak więc przykład łańcucha, który mam, to "5,45" i chcę mieć odpowiednik zmiennoprzecinkowy, abym mógł dodać do niego .1. Szukałem w Internecie, ale widzę tylko, jak przekonwertować ciąg na liczbę całkowitą.

Anton
źródło
Pytanie wymaga dalszych szczegółów. Czy ciąg składa się tylko z cyfr? Alfanumeryczne? Ok, jeśli usunięto alfy? Czy wynikowa liczba ma określony cel?
JGurtz

Odpowiedzi:

90

W ogóle nie musisz go konwertować:

% perl -e 'print "5.45" + 0.1;'
5.55
Alnitak
źródło
26
5.55 nie jest liczbą całkowitą
OrangeDog
15
@OrangeDog OP edytował pytanie (kilka miesięcy po opublikowaniu tej odpowiedzi) - oryginalne pytanie faktycznie zawierało liczby zmiennoprzecinkowe.
Alnitak
1
a co z porównaniami, gdy ciąg ma przecinek?
Ramy
[rabdelaz@Linux_Desktop:~/workspace/akatest_5]$perl -e 'print "nope\n" unless "1,000" > 10;' nope [rabdelaz@Linux_Desktop:~/workspace/akatest_5]$perl -e 'print "nope\n" if "1,000" > 10;'
Ramy
73

To proste rozwiązanie:

Przykład 1

my $var1 = "123abc";
print $var1 + 0;

Wynik

123

Przykład 2

my $var2 = "abc123";
print $var2 + 0;

Wynik

0
porquero
źródło
7
AFAIU to jedyna odpowiedź na to, o co pytano
Cougar
4
Uważaj podczas dodawania zera do łańcucha. Jeśli ciąg zaczyna się od „inf” lub „nan”, wartość nie będzie wynosić zero. Np. Moja $ var2 = "info123"; print $ var2 + 0: Wynik będzie: Inf
Rodrigo De Almeida Siqueira
Robiłem foreach my $i ('00'..'15')i musiałem usunąć w niektórych miejscach zera wiodące. To 0+rzucanie na liczbę również to osiąga.
stevesliva
Najwyraźniej to nie działa z ciągami szesnastkowymi: „0x14C” + 0 daje 0 (arrggg)
Allasso
41

Perl to język kontekstowy. Nie działa zgodnie z podanymi przez Ciebie danymi. Zamiast tego określa, jak traktować dane w oparciu o używane operatory i kontekst, w którym ich używasz. Jeśli zajmujesz się liczbami, otrzymujesz liczby:

# numeric addition with strings:
my $sum = '5.45' + '0.01'; # 5.46

Jeśli robisz różne rzeczy w postaci łańcuchów, otrzymasz ciągi:

# string replication with numbers:
my $string = ( 45/2 ) x 4; # "22.522.522.522.5"

Perl głównie wymyśla, co robić i jest to w większości prawidłowe. Innym sposobem wyrażenia tego samego jest to, że Perl bardziej troszczy się o czasowniki niż o rzeczowniki.

Próbujesz coś zrobić, ale to nie działa?

brian d foy
źródło
Wybacz mi brak wiedzy, ale nie do końca rozumiem twój drugi przykład. Dzielisz dwie liczby, a następnie mnożysz je, jak / dlaczego daje to ciąg?
gideon
4
Nie mnożę liczb. xJest operatorem replikacji łańcuch.
brian d foy
3
Czy nie powinno być my $string = ( 45/2 ) x 3; # "22.522.522.5"z 45 zamiast 44? W przeciwnym razie nie rozumiem, skąd pochodzi „.5” w wyniku ...
Vickster,
10

Google prowadził mnie tutaj podczas wyszukiwania tego samego pytania, które zadał phill (sortowanie pływaków), więc pomyślałem, że warto opublikować odpowiedź, mimo że wątek jest trochę stary. Jestem nowy w perlu i wciąż mam głowę wokół tego, ale stwierdzenie Briana d Foy: „Perl bardziej przejmuje się czasownikami niż rzeczownikami”. powyżej naprawdę uderza w gwóźdź w głowę. Nie musisz konwertować ciągów na zmiennoprzecinkowe przed zastosowaniem sortowania. Musisz powiedzieć sortowaniu, aby sortował wartości jako liczby, a nie jako łańcuchy. to znaczy

my @foo = ('1.2', '3.4', '2.1', '4.6');
my @foo_sort = sort {$a <=> $b} @foo;

Więcej informacji na temat sortowania można znaleźć pod adresem http://perldoc.perl.org/functions/sort.html

Norma
źródło
8

Jak rozumiem, funkcja int () nie jest przeznaczona jako funkcja „rzutowania” do wyznaczania typu danych, jest po prostu używana (ab) do zdefiniowania kontekstu jako arytmetycznego. Używałem (ab) w przeszłości (0 + $ val), aby upewnić się, że $ val jest traktowane jako liczba.

mccutchm
źródło
tak, int()jest „(ab) używany”; Rozumiem.
Sapphire_Brick
6
$var += 0

prawdopodobnie to, czego chcesz. Ostrzegamy jednak, że jeśli zmienna $ var jest ciągiem nie może zostać przekonwertowana na numeryczną, pojawi się błąd, a zmienna $ zmienna zostanie zresetowana do 0 :

my $var = 'abc123';
print "var = $var\n";
$var += 0;
print "var = $var\n";

dzienniki

var = abc123
Argument "abc123" isn't numeric in addition (+) at test.pl line 7.
var = 0
bez indeksów
źródło
3

Perl tak naprawdę ma tylko trzy typy: skalary, tablice i skróty. I nawet to rozróżnienie jest dyskusyjne. ;) Sposób traktowania każdej zmiennej zależy od tego, co z nią zrobisz:

% perl -e "print 5.4 . 3.4;"
5.43.4


% perl -e "print '5.4' + '3.4';"
8.8
Rini
źródło
5
Perl ma o wiele więcej typów niż, ale dla pojedynczych wartości jest to tylko jedna wartość.
brian d foy
1

W porównaniach ma znaczenie, czy skalar jest liczbą w ciągu. I nie zawsze jest to rozstrzygalne. Mogę zgłosić przypadek, w którym perl pobrał zmiennoprzecinkowy w notacji „naukowej” i użył tego samego w kilku wierszach poniżej w porównaniu:

use strict;
....
next unless $line =~ /and your result is:\s*(.*)/;
my $val = $1;
if ($val < 0.001) {
   print "this is small\n";
}

I tutaj $valnie został zinterpretowany jako numeryczny np. "2e-77"Pobrany z $line. Dodanie 0 (lub 0,0 dla dobrych programistów C) pomogło.

Steffen Moeller
źródło
0

Perl jest słabo napisany i oparty na kontekście. Wiele skalarów można traktować zarówno jako łańcuchy, jak i liczby, w zależności od używanych operatorów. $a = 7*6; $b = 7x6; print "$a $b\n";
Masz 42 777777.

Jest jednak subtelna różnica. Kiedy odczytujesz dane liczbowe z pliku tekstowego do struktury danych, a następnie przeglądasz je za pomocą Data::Dumper, zauważysz, że Twoje liczby są cytowane. Perl traktuje je wewnętrznie jako ciągi.
Czytaj: $my_hash{$1} = $2 if /(.+)=(.+)\n/;.
Wysypisko:'foo' => '42'

Jeśli chcesz nienotowanych numery zrzutu:
Odczyt: $my_hash{$1} = $2+0 if /(.+)=(.+)\n/;.
Wysypisko:'foo' => 42

Po tym, jak $2+0Perl zauważy, że potraktowałeś 2 dolary jako liczbę, ponieważ użyłeś operatora numerycznego.

Zauważyłem to, próbując porównać dwa skróty z Data::Dumper.

SzG
źródło