Seite 1 von 2

Division durch Null

Verfasst: Do 3. Okt 2013, 17:57
von Omega
Hallo,

ich habe mir ein Marko geschrieben, welches Makros aus dem Paket PGF nutzt.
Es wird in dem Makro durch eine Zahl geteilt, die ich mit "Divisor" bezeichne.
Da der Divisor variabel ist, kann seitens des Ablaufs der Fall einer Division durch Null erfolgen. Um diesen Fall auszuschließen, verwende ich die Funktion "ifthenelse" des PGF Paketes.
Leider wird jedoch scheinbar auch der Fall innerhalb der ifthenelse-Funktion durchgerechnet, der ja gerade von mir ausgeschlossen werden soll.

Hat jemand eine elegante und sinnvolle Lösung für meine Problemstellung?

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}

\newcommand\doit{%
	\pgfmathsetmacro\division{ifthenelse(notequal(\divisor,0),1/\divisor,7353)}
	\draw (0,0) node {\division};
}


\begin{document}
\begin{tikzpicture}
	\def\divisor{0}
	\doit
\end{tikzpicture}
\end{document}
Schönen Gruß

Verfasst: Do 3. Okt 2013, 18:33
von cgnieder
Vielleicht nicht so elegant, funktioniert aber:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}

\newcommand\doit{%
  \ifnum\divisor=0
    \pgfmathsetmacro\division{7353}
  \else
    \pgfmathsetmacro\division{1/\divisor}
  \fi
  \draw (0,0) node {\division};
}

\begin{document}
\begin{tikzpicture}
  \def\divisor{0}
  \doit
\end{tikzpicture}
\begin{tikzpicture}
  \def\divisor{3}
  \doit
\end{tikzpicture}

\end{document}
Grüße

Verfasst: Do 3. Okt 2013, 22:14
von Omega
Hey Clemens,

vielen Dank für deine schnelle Antwort!

Was ist jedoch für den Fall, wenn der Divisor in deiner Antwort eine Fließkommazahl ist? Ich erhalte dann eine Fehlermeldung.
\ifnum akzeptiert ja schließlich nur ganze Zahlen.

Schöne Grüße

Verfasst: Do 3. Okt 2013, 22:34
von cgnieder
Dann ändere
\ifnum\divisor=0 
in
\ifdim\divisor pt=0pt 
Grüße

Verfasst: Do 3. Okt 2013, 22:47
von Omega
Super! Danke! :D

Sehe ich es richtig, dass es für \ifdim nur die Relationen ">","<" und "=" gibt und damit kein Ungleich z.b. "!=" ?

Viele Grüße

Verfasst: Do 3. Okt 2013, 22:58
von cgnieder
Stimmt.

Ich sehe meine Antwort auch eher als Notlösung. Man müsste eigentlich nach der Ursache fanden, wieso der pgf-Code schiefgeht. Meiner Meinung nach sollte der falsch-Zweig nicht evaluiert werden, wenn er nicht benötigt wird, offenbar wird er das aber doch...

Vielleicht hat ja ein/e pgf-Experte/in eine Erklärung.

Grüße

Verfasst: Fr 4. Okt 2013, 01:18
von esdd
In der Doku habe ich folgendes gefunden:
"x" (group operators)
These operators are used to quote x . However, as every expression is expanded with \edef before
it is parsed, macros (e.g., font commands like \tt or \Huge) may need to be "protected" from this
expansion (e.g., \noexpand\Huge). Ideally, you should avoid such macros anyway. Obviously, these
operators should be used with great care as further calculations are unlikely to be possible with the
result.
Das verstehe ich so, dass in der Tat erst alles expandiert wird, bevor die Bedingung ausgewertet wird. An der Stelle folgt dann auch noch ein Beispiel mit ifthenelse. Das lässt sich auf obiges Problem übertragen:
\documentclass{article} 
\usepackage[utf8]{inputenc} 
\usepackage{tikz}

\newcommand\division{\pgfmathparse{1/\divisor}\pgfmathresult}

\newcommand\doit{%
  \draw (0,0) node {\pgfmathparse{\divisor > 0.0001 ? "\noexpand\division" : 7353}\pgfmathresult};%
}  

\begin{document} 
   \begin{tikzpicture}\def\divisor{0.05}\doit\end{tikzpicture}

   \begin{tikzpicture}\def\divisor{3}\doit\end{tikzpicture}

   \begin{tikzpicture}\def\divisor{0.00009}\doit\end{tikzpicture}
\end{document}
Darüber hinaus ist die Rechengenauigkeit von pgfmath begrenzt.

Gruß
Elke

Verfasst: Fr 4. Okt 2013, 16:06
von Omega
Das ist auch eine Lösung. Danke.

Was ist aber für den Fall, wenn ich das Ergebnis in ein \pgfmathsetmacro speichern möchte. Dies klappt bei mir nicht, da scheinbar \pgfmathsetmacro keine durch \newcommand erstellten Makros verarbeiten kann.

Hier ein Beispiel:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}

\newcommand\division{\pgfmathparse{1/\divisor}\pgfmathresult}

\newcommand\doit{%
	\draw (0,0) node[right] {\pgfmathparse{\divisor > 0.0001 ? "\noexpand\division" : 7353}\pgfmathresult};
	\pgfmathsetmacro\nr{\divisor > 0.0001 ? 1+"\noexpand\division" : 7353}
	\draw (3,0) node {\nr};
}  

\begin{document}
   \begin{tikzpicture}\def\divisor{0.05}\doit\end{tikzpicture}

   \begin{tikzpicture}\def\divisor{3}\doit\end{tikzpicture}

   \begin{tikzpicture}\def\divisor{0.00009}\doit\end{tikzpicture}
\end{document}
Gruß

Verfasst: Fr 4. Okt 2013, 16:17
von cgnieder
Omega hat geschrieben:Was ist aber für den Fall, wenn ich das Ergebnis in ein \pgfmathsetmacro speichern möchte. Dies klappt bei mir nicht, da scheinbar \pgfmathsetmacro keine durch \newcommand erstellten Makros verarbeiten kann.
Das ist nicht das Problem, sondern, dass \pgfmathresult nach Expansion von \doit im Zweifelsfall keine Zahl enthält! Du musst es expandieren lassen, damit danach in \pgfmathresult tatsächlich das gewünschte Ergebnis enthalten ist:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}

\newcommand\division{\pgfmathparse{1/\divisor}\pgfmathresult}

\newcommand\doit{%
   \draw (0,0) node[right] {\pgfmathparse{\divisor > 0.0001 ?
       "\noexpand\division" : 7353}\pgfmathresult};
   \pgfmathparse{\divisor > 0.0001 ? "\noexpand\division" : 7353}
   % \show\pgfmathresult % im log anzeigen, wie \pgfmathresult definiert ist
   \pgfmathresult
   % \show\pgfmathresult % im log anzeigen, wie \pgfmathresult definiert ist
   \pgfmathsetmacro\nr{\pgfmathresult}
   \draw (3,0) node {\nr};
}  

\begin{document}
   \begin{tikzpicture}\def\divisor{0.05}\doit\end{tikzpicture}

   \begin{tikzpicture}\def\divisor{3}\doit\end{tikzpicture}

   \begin{tikzpicture}\def\divisor{0.00009}\doit\end{tikzpicture}
\end{document}
Grüße

Verfasst: Fr 4. Okt 2013, 16:31
von Omega
Meiner Meinung nach entsteht eine gewisse Redundanz durch diese Methode,
was nicht gerade die Übersicht fördert.
Ich denke dabei an umfangreichere Varianten vom Makro \doit in der Praxis.

Findest du nicht, dass dein erster Lösungsvorschlag in der Praxis zweckdienlicher ist?


Gruß