使用 FPeval 的结果为表格单元格着色

使用 FPeval 的结果为表格单元格着色

我正在尝试根据表格单元格的数值为其赋予灰度颜色值。到目前为止,我有以下代码

\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}

表格中包含所有浮点数。我得到的错误是:

Undefined control sequence.
<argument> \resa 

有没有什么办法可以使用 FPeval 的结果来给单元格着色?

答案1

您可以添加行

\xdef\resa{\resa}%%

到您的代码中。但是仍然无法正确编译,因为您的乘数超出了 0 到 1 的范围。

\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}

为了得到可编译的版本,我写了

\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}

答案2

下面的示例通过展开\resa之前的\cellcolor内容并查看其参数来解决这个问题。

第二个问题是,颜色模型的范围gray在 0 到 1 之间(含 0 和 1)。当乘以 2 时,值 0.8 和 1.0 超出了该范围。因此,示例检查结果并在必要时将其限制为 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}

结果

还有一个版本,其中所有的数学运算都是通过fpmeans 完成的。此外,如果背景颜色太暗,文本颜色会切换为白色,以保持可读性。

\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}

结果

不过,还有改进的空间。数字结果两端有很多不必要的零,可以缩短,例如:

0.200000000000000000 ⇒ .2
0.400000000000000000 ⇒ .4
1.000000000000000000 ⇒ 1

\FPclip可以通过到和来删除末尾的零0.20.41

thepdfnumber更进一步,提供了\thepdfnumber缩短两端小数的方法,以获得.2.41。甚至更好的是,\thepdfnumberNormZeroOne它处理了灰度值的范围条件:

\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}

答案3

expl3使用及其强大的模块的更简单的解决方案fp

\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}

为了测试目的,该\hetest命令还会以红色打印参数和计算的颜色值。

在此处输入图片描述

变体 1

如果灰度低于 0.5,则参数将打印为白色

\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}

变体 2

与以前相同,但值存储在fp变量中;出于性能原因,如果计算量较大,这可能会很方便。

在这里我定义了语法糖\__ecker_cellcolor:n,以便\cellcolor[gray]{...}我们可以使用变体在调用时使用扩展来扩展值f

\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}

变体 1 和 2 的输出

在此处输入图片描述

答案4

xintexpr使用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}

在此处输入图片描述

宏的使用\xinttheiexpr [2]表示生成小数点后有 2 位数字的定点数。

注意:这样做是可行的,因为事实证明\cellcolor宏会在某个时候扩展其参数,所以我们不必事先这样做。请参阅下面 Variant2 中的注释,了解如果使用的宏比 更不宽容,可以如何继续\cellcolor

变体 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}

在此处输入图片描述

变体 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}

它产生的结果与变体 1 相同。

相关内容