Schrift
[thread]11614[/thread]

'z' == 0 ist gleich true?

Leser: 3


<< >> 9 Einträge, 1 Seite
Gast Gast
 2008-04-09 19:38
#108171 #108171
Habe hier aus Perl in 21 Tagen eine Codeschnipsel, den ich nicht verstehe:
Code (perl): (dl )
1
2
3
4
5
6
while () {
     print 'Geben Sie die zu buchstabierende Zahl ein: ';
     chomp($num = <STDIN>);
     if ($num ne "0" && $num == 0) { # wenn $num ein String
     ... 
}

Es geht hier um eine Eingabevalidierung (Es dürfen nur Zahlen im einstelligen Bereich eingegeben werden und der Autor erklärt Zeile 4 folgendermassen:
wenn $num nicht das Zeichen 0 ist, aber im numerischen Vergleich zu 0 ausgewertet wird, muss $num ein String sein ?????
Kurzum, es funktioniert und vereinfacht man die If-Anweisung zu:
Code (perl): (dl )
if ('z' == 0){doSomeThing();}

wird der If-Block auch ausgeführt. Lediglich bei eingeschalteter Warnung motzt der Interpreter ein bißchen, führt die Anweisung aber trotzdem aus.
Bin jetzt schon eine ganze Weile am grübeln und googeln, habe aber überhaupt keine Idee, wo der Hase im Pfeffer liegt.

Ein paar klärende Worte würden mir gut über die Nacht helfen.
sid burn
 2008-04-09 20:20
#108175 #108175
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Es gibt zwei unterschiedliche Vergleiche.

Einmal den String vergleich und einmal einen Zahlenvergleich. Beide sind unterschiedlich und du selber musst sagen was du haben möchtest. Die Operatoren die aus Zeichen bestehen sind für Zahlenvergleiche gedacht.

==, >=, <=, !=

Die Operatoren die aus Buchstaben bestehen sind für String Vergleiche.

eq, gt, lt, ne

Wenn du einen Operator für einen Zahlenvergleich nutzt dann werden beide Variablen auf jeder Seite zuerst in Zahlen umgewandelt und dann miteinander verglichen.

'z' == 0

bedeutet also das das 'z' in einer Zahl umgewandelt wird. Bei der Umwandlung von Strings nach Zahlen geht perl so das die ersten Zahlen im String als Zahl betrachtet werden. Kommt am anfang keine Ziffern vor wird daraus automatisch eine 0.

Daher vergleichst du hier in echt 0 == 0 was natürlich wahr ist und somit wird dein if block ausgeführt.

warnings solltest du definitiv an lassen. Weil dir Perl eben ein warning ausspuckt wenn du eine Variable umwandelst die nicht 100%ig als Zahl darstellbar ist.

da du selber ja eher ein String vergleichen möchtest oder ein Passwort wäre hier ein 'eq' Korrekt.

'z' eq 0

Hier würde er beides zuerst in einem String umwandeln. Ein vergleich mit eq wirft nie ein warning. Hier vergleicht er also "z" mit "0" und das ist natüprlich unwahr.

Im übrigen würde ich jetzt nicht auf die Idee kommen überall eq zu verwenden. Du musst das richtige nehmen je nachdem ob du eine zahl oder einen String vergleichst. Wenn eq für Zahlen vergleich nutzt wäre das auch falsch, und es kommt nichtmal ein warning.

Kurzes beispiel hierfür. Stell dir vor du fragst den benutzern zwei zahlen einzugeben und du überprüfst danach ob die Zahlen gleich sind.

Der Nutzer gibt einmal "0" und einmal "0.0" ein. Als Zahl verglichen sind beide Sachen identisch da sie eben "0" sind. Als String verglichen sind sie inkorrekt. Da du den String "0" der ein zeichen groß ist mit einem String Vergleichst der drei Zeichen groß ist. Und aus einer Null + Punkt + Null besteht.

Ich hoffe der Unterschied wird dir jetzt klar.

Diese Unterscheidung haben zu können ist dementsprechend auch wichtig.


Bei größer/kleiner Vergleichen wird es sogar noch deutlicher wenn du die Falschen Operatoren nutzt. Beispielsweise ist

2 gt 1234567

wahr. Den die zwei kommt nach der 1. Das ist das Gleiche als wenn du du Wörter einordnest "b" kommt auch nach "auto".

Wenn du >= nutzt ist 2 >= 1234567 natürlich falsch da die Zahlen eben auch als Zahlen angesehen wird.


Nur zum Flamen:
PHP kennt sowas nicht. Wenn du eine "0" eingibst wird eine Konversion zu einer zahl auf beiden Seiten gemacht. Es gibt keine warnings weder kannst du erzwingen das es Strings oder Zahlen vergleichen soll. ;)
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
Gast Gast
 2008-04-09 20:58
#108179 #108179
Moin sid burn,
also erstmal besten Dank für ebenso ausführliche wie perfekte Antwort, da bleiben eigentlich keine Fragen mehr offen.
Was die warnings angeht (genauso wie übrigens use strict), hast Du natürlich recht, da einem dann ein sauberer (fehlerfreier?) Programmierstil, wie ich ihn von streng typisierten Sprachen wie Java kenne, aufgezwungen wird.
Da ich momentan aber gerade dabei bin, mir die Basics von Perl einzuimpfen, schalte ich den ganzen Krempel meistens aus, da ich auf diese Weise auch mal nen Schuss ins Blaue wagen kann, bzw. ich schalte es, wenn alles funktioniert, wieder ein, um zu sehen, ob die die Maschine dann immer noch läuft.
Wenn ich dann mal so weit bin, ernsthafte Programme schreiben zu wollen, dann natürlich nur noch mit use (strict|warnings).

Bis die Tage
pq
 2008-04-09 21:19
#108183 #108183
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
also ich empfehle, immer warnings und strict anzuhaben, so merkst du eben gleich, wo
du einen fehler drin hast. das erspart dir arbeit.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
betterworld
 2008-04-09 21:26
#108184 #108184
User since
2003-08-21
2613 Artikel
ModeratorIn

user image
Gast+2008-04-09 18:58:54--
Da ich momentan aber gerade dabei bin, mir die Basics von Perl einzuimpfen, schalte ich den ganzen Krempel meistens aus, da ich auf diese Weise auch mal nen Schuss ins Blaue wagen kann

Kannst du schon machen, trotzdem kann man wohl nicht leugnen, dass Du den Fehler schnell gefunden haettest, wenn Du die Warnungen beachtet (und aktiviert) haettest.
murphy
 2008-04-10 02:38
#108194 #108194
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
sid burn+2008-04-09 18:20:01--
[...] warnings solltest du definitiv an lassen. Weil dir Perl eben ein warning ausspuckt wenn du eine Variable umwandelst die nicht 100%ig als Zahl darstellbar ist. [...]


Das stimmt nicht ganz, denn es gibt einen esoterischen Spezialfall: Wenn ein String exakt den Inhalt '0 but true' hat, dann verursacht er bei der Konversion in eine Zahl keine Warnung. Das Resultat dieser Konversion ist, wie zu erwarten, Null.

Der Sinn dieser merkwürdigen Ausnahme findet sich in -f ioctl.

Trotzdem ist die Verwendung von warnings natürlich sinnvoll :-)
When C++ is your hammer, every problem looks like your thumb.
betterworld
 2008-04-10 04:26
#108195 #108195
User since
2003-08-21
2613 Artikel
ModeratorIn

user image
murphy+2008-04-10 00:38:23--
Der Sinn dieser merkwürdigen Ausnahme findet sich in -f ioctl.

Wenn Du meinst, dass DAS merkwürdig ist, kanntest Du wohl noch nicht den Unterschied zwischen:
Code: (dl )
1
2
perl -we "q(di)"
perl -we "q(id)"

;-)
murphy
 2008-04-10 05:20
#108198 #108198
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
@betterworld: Den kannte ich tatsächlich noch nicht. Gibt's für dieses Verhalten auch einen dokumentierten Grund?
When C++ is your hammer, every problem looks like your thumb.
betterworld
 2008-04-10 17:32
#108220 #108220
User since
2003-08-21
2613 Artikel
ModeratorIn

user image
murphy+2008-04-10 03:20:53--
@betterworld: Den kannte ich tatsächlich noch nicht. Gibt's für dieses Verhalten auch einen dokumentierten Grund?

Es hat afaik irgend etwas mit nroff zu tun. Eine praktische Anwendung wuerde ich aber auch gerne mal sehen.
Hier steht noch ein bisschen darueber: http://www.perlmonks.org/?node_id=475466
<< >> 9 Einträge, 1 Seite



View all threads created 2008-04-09 19:38.