PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : \ifnum mit Dezimalzahlen



texnicker
15-03-2012, 11:38
Hallo Leute.
Ich tüftele seit einer Woche an einem Problem mit if-Abfragen herum. In einer Arbeit will ich den Signifikanzwert (p) so eingeben, wie er berechnet wurde (z. B. 0,00123). In der Ausgabe sollen die Werte dann gerundet bzw. übersetzt werden, üblich ist die Angabe (p < 0,05 oder, wenn p > 0,05 ist p = n. s. [nicht signifikant]).
Mit Skriptsprachen habe ich etwas Erfahrung aber TeX treibt mich in den Wahnsinn.
Folgendes Minimalbeispiel erzeugt im PDF zum Beispiel die Zeile
0.123: .123¡0.05p <= 0.05.
Die \ifnum-Anweisung wird einfach ausgegeben! Beispiele wie einfache Schleifen in einem Latex-Kommando (http://www.mrunix.de/forums/showthread.php?t=67965) führen mich leider nicht weiter. Vielleicht könnt ihr mir helfen?!
Die Angabe der Zahlen mit Komma (0,05) ändert nichts. Die Übersetzung nach ifthenelse (http://de.wikibooks.org/wiki/LaTeX-W%C3%B6rterbuch:_ifthenelse) mit dem ifthen-Paket erzeugt den gleichen Unsinn.



\documentclass{article}

\newcommand*\pvalue[1]
{
#1:
\ifnum#1<=0.05%
p $<=0.05$ % wenn p <= 0.05
\else
$p = $ #1 (n.~s.) % wenn p > 0.05 (nicht signifikant)
\fi
\\
}

\begin{document}

\pvalue{0.123}\\
\pvalue{0.0123}\\
\pvalue{0.00123}\\
\pvalue{0.000123}\\

\end{document}

cgnieder
15-03-2012, 12:12
Vielleicht wäre das fp (http://www.ctan.org/pkg/fp) Paket was:

\documentclass{article}
\usepackage{fp}
\def\mynum{}

\newcommand*\pvalue[1]{%
#1: %
\FPset\mynum{#1}%
\FPiflt\mynum{.05}%
$p=$ #1 (n.~s.)%
\else
$p\geq0.05$%
\fi
, gerundet: \FPround\mynum\mynum{2}\FPprint\mynum
}

\begin{document}

\pvalue{0.123}\\
\pvalue{0.0123}\\
\pvalue{0.00123}\\
\pvalue{0.000123}

\end{document}

Gruß

texnicker
15-03-2012, 12:56
Danke, Clemens! Das war der Druchbruch!
Anbei ein Minimalbeispiel, falls noch jemand anderes außer mir mit Latex herumdoktort.

\documentclass{article}
\usepackage{fp}

%% Das Paket definiert viele Funktionen, hier sind die binären Verhältnisse relevant:
%introduction of new values
%\FPset#1#2 % #1 := #2 (#1 may be macro or string)
%%binary relations
%\FPiflt#1#2...\else...\fi % #1 < #2 ?
%\FPifeq#1#2...\else...\fi % #1 = #2 ?
%\FPifgt#1#2...\else...\fi % #1 > #2


\def\mynum{}
\newcommand*\pvalue[1]{%
\FPset{\pval}{#1}%
\FPiflt{\pval}{.001}%
$p<0.001$%
\else
\FPiflt{\pval}{.01}%
$p<0.01$%
\else
\FPiflt{\pval}{.05}%
$p<0.05$%
\else
$p =$ n.~s.% das %-Zeichen beendet die Zeile, damit keine Leerzeichen weitergegeben werden
\fi
\fi
\fi
}

\begin{document}

Es fand sich kein Unterschied in der Koerperhoehe der untersuchten Hunde (\pvalue{0.123}). Sie hatten jedoch ein unterschiedliches Alter (\pvalue{0.0123}) und unterschiedlich lange Schnautzen (\pvalue{0.00123}). Im Vergleich mit Maeusen unterschied sich die Koerpergroeße hoechst signifikant (\pvalue{0.000123}).

\end{document}

texnicker
17-03-2012, 15:49
Beim Erstellen der PDF-Datei erscheint ein

extra \fi für alle Zahlen, die kleiner als 0.05 sind. Wenn die Schleife zum Beispiel bis \FPiflt{\pval}{.01} durchlaufen wird und dieser Wert true ist, dann wird $p<0.01$ ausgegeben und ein \fi ist zu viel. Bei Zahlen < 0,001 sogar zweimal. - Versteht jemand, warum? ... und vor allem, wie man das beheben kann?
Reproduzierbar mit meinem Minimalbeispiel von oben.

mechanicus
17-03-2012, 15:59
Hi,

eine alternative mit expl3:


\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \pvalue { m }
{
\dim_compare:nTF {#1 pt <= 0.05 pt }
{ $p \leq 0.05$ } % wenn p <= 0.05
{ $p = #1~\text{(n.~s.)}$ } % wenn p > 0.05 (nicht signifikant)
}
\ExplSyntaxOff
\begin{document}

\pvalue{0.123}\\
\pvalue{0.0123}\\
\pvalue{0.00123}\\
\pvalue{0.000123}\\

\end{document}

Marco

cgnieder
17-03-2012, 16:08
Sowas, wollte gerade dasselbe vorschlagen:

\documentclass{article}

\usepackage{expl3}
\ExplSyntaxOn
\newcommand* \pvalue [1]
{
\fp_compare:nNnTF { #1 } < { .001 }
{ $p<0.001$ }
{
\fp_compare:nNnTF { #1 } < { .01 }
{ $p<0.01$ }
{
\fp_compare:nNnTF { #1 } < { .05 }
{ $p<0.05$ }
{ $p =$~n.~s. }
}
}
}
\ExplSyntaxOff
\begin{document}
\pvalue{.04}

\pvalue{.005}

\pvalue{.0005}
\end{document}

Verschachtelte \if -Abfragen sind immer tricky (finde auf die Schnelle leider nicht die Referenz, die ich im Hinterkopf habe). expl3 (http://www.ctan.org/pkg/expl3) hat hier erstens die sichereren und zweitens die m.E. bequemeren Conditionals.

An die Syntax muss man sich zwar erst gewöhnen, danach ist sie aber ziemlich selbsterklärend.

Gruß

mechanicus
17-03-2012, 16:32
Hi,

@Clemens. Die Idee finde ich gut. Ich würde vermutlich eine alternative case-Umgebung bauen.

Marco

cgnieder
17-03-2012, 16:50
Wenn ich ein bisschen mehr Zeit gehabt hätte(*), würde ich das auch ein klein wenig anders versuchen. Gibt es es nicht
\prg_cases das man verwenden könnte?

(*) unterwegs, den St. Patricks Day zu feiern :)

Gruß

mechanicus
17-03-2012, 16:53
Hi,

es gibt prg_case_int:nnn oder prg_case_dim:nnn oder prg_case_str:nnn ... aber kein fp ;-) und die Programmierung der Fälle ist jeweils mit dem Relationszeichen =. Man müsste also eine eigene Funktion bauen.

Viel Spaß auf deiner Tour.

Marco

mechanicus
17-03-2012, 18:26
Hi,

mit Hilfe von Joseph Wright gibt es nun eine Möglichkeit:


\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new:Npn \prg_relation_case_dim:nnn #1
{
\tex_romannumeral:D
\exp_args:Nf \prg_relation_case_dim_aux:nnn { \dim_eval:n {#1} }
}
\cs_new:Npn \prg_relation_case_dim_aux:nnn #1#2#3
{ \prg_relation_case_dim_aux:nw {#1} #2 { = #1 } {#3} \q_recursion_stop }
\cs_new:Npn \prg_relation_case_dim_aux:nw #1#2#3
{
\dim_compare:nTF {#1#2}
{ \prg_case_end:nw {#3} }
{ \prg_relation_case_dim_aux:nw {#1} }
}

\NewDocumentCommand \pvalue { m }
{
\prg_relation_case_dim:nnn {#1 pt}
{
{<= 0.01 pt } { $p \leq 0.01$ }
{<= 0.02 pt } { $p \leq 0.02$ }
{<= 0.05 pt } { $p \leq 0.05$ }
}
{ $p > 0.05$ }
}
\ExplSyntaxOff
\begin{document}
\pvalue{.04}

\pvalue{.018}

\pvalue{.0005}

\pvalue{1}
\end{document}

Marco

cgnieder
18-03-2012, 11:49
@Marco: nice :)

Ohne expl3 ginge auch das hier:

\documentclass{article}
\usepackage{fp}


\makeatletter
\newcommand*\pvalue[1]{%
\FPset{\pval}{#1}%
\FPiflt{\pval}{.001}%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{$p<0.001$}%
{%
\FPiflt{\pval}{.01}%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{$p<0.01$}%
{%
\FPiflt{\pval}{.05}%
$p<0.05$%
\else
$p =$ n.~s.%
\fi
}%
}%
}
\makeatother

\begin{document}

\pvalue{.04}

\pvalue{.005}

\pvalue{.0005}

\end{document}
Durch \@firstoftwo und \@secondoftwo wird garantiert, dass keine neue if-Abfrage innerhalb einer anderen ausgeführt wird. Damit wird dann auch die »extra fi« Warnung vermieden.

Gruß

texnicker
18-03-2012, 16:51
Danke allen Mithelfenden!
Anbei für alle, die doktorn:



\documentclass{article}

\usepackage{siunitx}
\usepackage{expl3}


\ExplSyntaxOn
\newcommand* \pvalue [2][none]
% erfordert die Eingabe des p-Wertes
% als optionaler Parameter können
% lessthan für die Angabe 'p < #2', wenn das Statistikprogramm als Wert '<0,0001' ausgibt und man diesen Wert in der tex-Datei speichern will
% oder
% exact für die Ausgabe des exakten p-Wertes also z. B.: 'p = 0,0123'
% oder
% aprox für die Ausgabe einen Nährungswertes mit dem \aprox-Symbol
% ... verwendet werden.
% #2 ist das erforderliche Argument, #1 das optionale, das, wenn ungesetzt, 'none' ist
{
\str_if_eq:nnTF { #1 } { lessthan }
{ p\,$<$\,\num{#2} }
{%
\str_if_eq:nnTF { #1 } { exact }
{ p\,$=$\,\num{#2} }
{ \str_if_eq:nnTF { #1 } { approx }
{ p\,$\approx$\,\num{#2} }
{
\fp_compare:nNnTF { #2 } < { .001 } %nNnTF compares floating numbres = < oder > Ergebnis ist (T)rue oder (F)alse
{ p\,$<$\,\num{0.001} }
{
\fp_compare:nNnTF { #2 } < { .01 }
{ p\,$<$\,\num{0.01} }
{
\fp_compare:nNnTF { #1 } < { .05 }
{ p\,$<$\num{0.05} }
{ p\,$=$\,~n.~s. }
}
}
}
}
}

}
\ExplSyntaxOff

\begin{document}

\pvalue{0.123}\\
\pvalue{0.0123}\\
\pvalue[exact]{0.024413}\\
\pvalue[approx]{0.0532}\\
\pvalue[lessthan]{0.003}\\
\pvalue{0.00123}\\
\pvalue{0.000123}

\end{document}

mechanicus
18-03-2012, 17:08
Hi,

nutze in Verbindung mit expl3 nicht newcommand. Entweder die Vorteile von xparse mittels NewDocumentCommand oder cs_new:Npn.

Marco