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ą.


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

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

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?


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


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.


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

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

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.


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.