Verwenden Sie das Ergebnis von FPeval, um eine Tabellenzelle einzufärben

Verwenden Sie das Ergebnis von FPeval, um eine Tabellenzelle einzufärben

Ich versuche, einer Tabellenzelle einen Graustufenfarbwert basierend auf ihrem numerischen Wert zuzuweisen. Bisher habe ich den folgenden Code

\documentclass{article}
\usepackage{fp,xcolor,colortbl}
\FPeval{\resb}{0.5}

\newcommand{\he}[1]{%
    \FPeval{\resa}{2 * #1}%
    \cellcolor[gray]{\resa}%
    #1 
}

\begin{document}
\begin{tabular}{| c | c | c |}
    \hline
    \he{0.1} & \he{0.2} & \he{0.3} \\
    \hline
    \he{0.5} & \he{0.8} & \he{1.0} \\
    \hline
\end{tabular}
\end{document}

Die Tabellen enthalten alle Gleitkommazahlen. Der Fehler, den ich erhalte, ist:

Undefined control sequence.
<argument> \resa 

Gibt es eine Möglichkeit, das Ergebnis von FPeval zum Einfärben der Zelle zu verwenden?

Antwort1

Sie könnten die Zeile hinzufügen

\xdef\resa{\resa}%%

zu Ihrem Code. Aber die Kompilierung funktioniert trotzdem nicht, weil Ihr Multiplikator Sie aus dem Bereich von 0 bis 1 bringt.

\documentclass{article}
\usepackage{fp,xcolor,colortbl}
\FPeval{\resb}{0.5}

\newcommand{\he}[1]{%
    \FPeval{\resa}{2 * #1}%
    \xdef\resa{\resa}%%
    \cellcolor[gray]{\resa}%
    #1 
}

\begin{document}

\begin{tabular}{| c | c | c |}
    \hline
    \he{0.1} & \he{0.2} & \he{0.3} \\
    \hline
    \he{0.5} & \he{0.8} & \he{1.0} \\
    \hline
\end{tabular}

\end{document}

Um eine kompilierbare Version zu erhalten, schrieb ich

\documentclass{article}
\usepackage{fp,xcolor,colortbl}
\FPeval{\resb}{0.5}

\newcommand{\he}[1]{%
    \FPeval{\resa}{2 * #1}%
    \xdef\resa{\resa}%%
    \ifdim\resa pt>1pt\relax
      \gdef\resa{1}%%
    \fi
    \cellcolor[gray]{\resa}%
    #1 
}

\begin{document}

\begin{tabular}{| c | c | c |}
    \hline
    \he{0.1} & \he{0.2} & \he{0.3} \\
    \hline
    \he{0.5} & \he{0.8} & \he{1.0} \\
    \hline
\end{tabular}

\end{document}

Antwort2

Das folgende Beispiel löst das Problem, indem es \resavor \cellcolorder Erweiterung erweitert wird und seine Argumente betrachtet.

Das zweite Problem ist, dass der Wertebereich für das Farbmodell grayzwischen 0 und 1 liegt. Die Werte 0,8 und 1,0 überschreiten diesen Wert, wenn sie mit 2 multipliziert werden. Daher prüft das Beispiel das Ergebnis und begrenzt es bei Bedarf auf 1.

\documentclass{article}
\usepackage{fp,xcolor,colortbl}

\newcommand{\he}[1]{%
    \FPeval{\resa}{2 * #1}%
    \ifdim\resa pt>1pt %
      \def\resa{1}%
    \fi
    \edef\processme{\noexpand\cellcolor[gray]{\resa}}%
    \processme
    #1%
}

\begin{document}
\begin{tabular}{| c | c | c |}
    \hline
    \he{0.1} & \he{0.2} & \he{0.3} \\
    \hline
    \he{0.5} & \he{0.8} & \he{1.0} \\
    \hline
\end{tabular}
\end{document}

Ergebnis

Und eine Version, bei der die gesamte Berechnung mit Mittelwerten durchgeführt wird fp. Außerdem wird die Textfarbe auf Weiß umgestellt, wenn die Hintergrundfarbe zu dunkel wird, um die Lesbarkeit aufrechtzuerhalten.

\documentclass{article}
\usepackage{fp,xcolor,colortbl}

\newcommand{\he}[1]{%
    \FPeval{\resa}{max(0, min(1, 2 * #1))}%
    \edef\processme{\noexpand\cellcolor[gray]{\resa}}%
    \processme
    \FPiflt{\resa}{0.5}%
      \color{white}%
    \fi
    #1%
}

\begin{document}
\begin{tabular}{| c | c | c |}
    \hline
    \he{0.1} & \he{0.2} & \he{0.3} \\
    \hline
    \he{0.5} & \he{0.8} & \he{1.0} \\
    \hline
\end{tabular}
\end{document}

Ergebnis

Dennoch besteht noch Verbesserungsbedarf. Das Zahlenergebnis hat an beiden Enden viele unnötige Nullen, die gekürzt werden können, z. B.:

0.200000000000000000 ⇒ .2
0.400000000000000000 ⇒ .4
1.000000000000000000 ⇒ 1

Die Nullen am Ende können durch \FPclip, 0.2und 0.4entfernt werden 1.

Das Paket thepdfnumbergeht noch einen Schritt weiter und ermöglicht \thepdfnumberdas Kürzen der Dezimalzahlen an beiden Enden .2, um , .4und zu erhalten 1. Noch besser ist, \thepdfnumberNormZeroOnedass es sich um die Bereichsbedingung für die Grauwerte kümmert:

\documentclass{article}
\usepackage{fp,xcolor,colortbl}

\usepackage{thepdfnumber}

\newcommand{\he}[1]{%
    \FPeval{\resa}{2 * #1}%
    \edef\processme{%
      \noexpand\cellcolor[gray]{\thepdfnumberNormZeroOne\resa}%
    }%
    \processme
    \FPiflt{\resa}{0.5}%
      \color{white}%
    \fi
    #1%
}

\begin{document}
\begin{tabular}{| c | c | c |}
    \hline
    \he{0.1} & \he{0.2} & \he{0.3} \\
    \hline
    \he{0.5} & \he{0.8} & \he{1.0} \\
    \hline
\end{tabular}
\end{document}

Antwort3

Eine einfachere Lösung mithilfe expl3des leistungsstarken fpModuls.

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\he}{m}
 {
  \cellcolor[gray]{ \fp_eval:n { min ( 2*#1, 1 ) } }
  #1
 }
\NewDocumentCommand{\hetest}{m}
 {
  \cellcolor[gray]{ \fp_eval:n { min ( 2*#1, 1 ) } }
  \textcolor{red}{#1 ~ -- ~ \fp_eval:n { min ( 2*#1, 1 ) }}
 }
\ExplSyntaxOff

\begin{document}

\begin{tabular}{| c | c | c |}
\hline
\he{0.1} & \he{0.2} & \he{0.3} \\
\hline
\he{0.5} & \he{0.8} & \he{1.0} \\
\hline
\end{tabular}
\qquad
\begin{tabular}{| c | c | c |}
\hline
\hetest{0.1} & \hetest{0.2} & \hetest{0.3} \\
\hline
\hetest{0.5} & \hetest{0.8} & \hetest{1.0} \\
\hline
\end{tabular}

\end{document}

Der \hetestBefehl druckt zu Testzwecken auch das Argument und den berechneten Farbwert (in Rot).

Bildbeschreibung hier eingeben

Variante 1

Das Argument wird weiß gedruckt, wenn der Grauwert unter 0,5 liegt.

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\he}{m}
 {
  \cellcolor[gray]{ \fp_eval:n { min ( 2 * #1 , 1 ) } }
  \fp_compare:nT { 2 * #1 < 0.5 } { \color{white} }
  #1
 }
\ExplSyntaxOff

\begin{document}

\begin{tabular}{| c | c | c |}
\hline
\he{0.1} & \he{0.2} & \he{0.3} \\
\hline
\he{0.5} & \he{0.8} & \he{1.0} \\
\hline
\end{tabular}

\end{document}

Variante 2

Dasselbe wie zuvor, aber die Werte werden in fpVariablen gespeichert. Dies kann aus Leistungsgründen praktisch sein, wenn die Berechnungen umfangreicher sind.

Hier definiere ich syntaktische Vereinfachung \__ecker_cellcolor:n, sodass \cellcolor[gray]{...}wir mit einer Variante den Wert zum Aufrufzeitpunkt mithilfe der fErweiterung erweitern können.

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\he}{m}
 {
  \ecker_he:n { #1 }
 }

\fp_new:N \l_ecker_resa_fp
\fp_new:N \l_ecker_resb_fp
\cs_new_protected:Npn \ecker_he:n #1
 {
  \fp_set:Nn \l_ecker_resa_fp { 2 * #1 }
  \fp_set:Nn \l_ecker_resb_fp { min ( \l_ecker_resa_fp, 1 ) }
  \__ecker_cellcolor:f { \l_ecker_resb_fp }
  \fp_compare:nT { \l_ecker_resb_fp < 0.5 } { \color{white} }
  #1
 }
\cs_new_protected:Npn \__ecker_cellcolor:n #1
 {
  \cellcolor[gray]{ \fp_eval:n { #1 } }
 }
\cs_generate_variant:Nn \__ecker_cellcolor:n { f }
\ExplSyntaxOff

\begin{document}

\begin{tabular}{| c | c | c |}
\hline
\he{0.1} & \he{0.2} & \he{0.3} \\
\hline
\he{0.5} & \he{0.8} & \he{1.0} \\
\hline
\end{tabular}

\end{document}

Ausgabe der Varianten 1 und 2

Bildbeschreibung hier eingeben

Antwort4

Eine einfache Lösung mit dem xintexprModul aus dem Bundle xint:

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{xintexpr}

\newcommand\he[1]{%
  \cellcolor[gray]{\xinttheiexpr[2] min(2*#1, 1)\relax}%
  #1%
}

\newcommand\hetest[1]{%
  \cellcolor[gray]{\xinttheiexpr[2] min(2*#1, 1)\relax}%
  \textcolor{red}{#1 -- \xinttheiexpr[2] min(2*#1, 1)\relax}%
}

\begin{document}

\begin{tabular}{| c | c | c |}
\hline
\he{0.1} & \he{0.2} & \he{0.3} \\
\hline
\he{0.5} & \he{0.8} & \he{1.0} \\
\hline
\end{tabular}
\qquad
\begin{tabular}{| c | c | c |}
\hline
\hetest{0.1} & \hetest{0.2} & \hetest{0.3} \\
\hline
\hetest{0.5} & \hetest{0.8} & \hetest{1.0} \\
\hline
\end{tabular}

\end{document}

Bildbeschreibung hier eingeben

Die Makros dienen \xinttheiexpr [2]dazu, Festkommazahlen mit zwei Nachkommastellen zu erzeugen.

NB: Dies funktioniert, weil sich herausstellt, dass \cellcolordas Makro an einem bestimmten Punkt sein Argument erweitert, sodass wir dies nicht vorher tun müssen. Siehe die Kommentare in Variante 2 weiter unten, um zu erfahren, wie man vorgehen könnte, wenn das verwendete Makro weniger nachsichtig wäre als \cellcolor.

Variante 1

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{xintexpr}

\newcommand{\he}[1]{%
  \cellcolor[gray]{\xinttheiexpr[2] min ( 2 * #1 , 1 ) \relax}%
  \xintifboolexpr{ 2 * #1 < 0.5 }{\color{white}}{}%
  #1%
}

\begin{document}

\begin{tabular}{| c | c | c |}
\hline
\he{0.1} & \he{0.2} & \he{0.3} \\
\hline
\he{0.5} & \he{0.8} & \he{1.0} \\
\hline
\end{tabular}

\end{document}

Bildbeschreibung hier eingeben

Variante 2

\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{xintexpr}

\makeatletter

\newcommand{\he}[1]{\ecker@he{#1}}

\protected\def\ecker@he #1{%
   \xdef\ecker@he@resa{\xintexpr 2*#1 \relax}%
   \xdef\ecker@he@resb{\xintexpr min(\ecker@he@resa,1) \relax}%
   \cellcolor[gray]{\xinttheiexpr[2] \ecker@he@resb \relax}%
   \xintifboolexpr{ \ecker@he@resb < 0.5 }{\color{white}}{}%
   #1%
}

% if \cellcolor did not f-expand its argument we would have used something
% like, perhaps,
% \protected\def\ecker@cellcolor@f #1{%
%    \expandafter\ecker@cellcolor@n\expandafter{\romannumeral-`0#1}%
% }

% \protected\def\ecker@cellcolor@n #1{%
%    \cellcolor[gray]{#1}%
% }

% and the call would have been
%    \ecker@cellcolor@f{\xinttheiexpr[2] \ecker@he@resb \relax}
% We need the iexpr[2] encapsulation because variable \ecker@he@resb
% was defined with \xintexpr, variant:
% \xdef\ecker@he@resb{\xintiexpr[2] min(\ecker@he@resa,1) \relax}%
% Then we would have done
%    \ecker@cellcolor@f{\xintthe\ecker@he@resb}


% We 
\makeatother

\begin{document}

\begin{tabular}{| c | c | c |}
\hline
\he{0.1} & \he{0.2} & \he{0.3} \\
\hline
\he{0.5} & \he{0.8} & \he{1.0} \\
\hline
\end{tabular}

\end{document}

Das Ergebnis ist das gleiche wie bei Variante 1.

verwandte Informationen