![动态数区间换算表](https://linux22.com/image/445397/%E5%8A%A8%E6%80%81%E6%95%B0%E5%8C%BA%E9%97%B4%E6%8D%A2%E7%AE%97%E8%A1%A8.png)
我是一名教师,我需要在所有考试中使用一个表格,将所谓的“价值点”间隔转换为 0 至 20 之间的点数。我使用下表:
\documentclass[addpoints,12pt]{exam}
\newcolumntype{?}[1]{!{\vrule width #1}} % to have bold vertical line in tabular
\usepackage{makecell} % to be able to use \\ linebreaks in tabular
\begin{document}
\setlength\tabcolsep{0.25em}
{\renewcommand{\arraystretch}{1}% for the vertical padding
\begin{tabular}{| p{1.3cm} |c | c | c | c | c | c | c | c | c | c ?{1mm} c | c | c | c | c | c | c | c | c | c | c |}
\hline
Value points & \makecell{0\\-\\3} & \makecell{4\\-\\7} & \makecell{8\\-\\11} & \makecell{12\\-\\15} & \makecell{16\\-\\19} & \makecell{20\\-\\23} & \makecell{24\\-\\27} & \makecell{28\\-\\31} & \makecell{32\\-\\35} & \makecell{36\\-\\39} &
\makecell{40\\-\\43} & \makecell{44\\-\\47} & \makecell{48\\-\\51} & \makecell{52\\-\\55} & \makecell{56\\-\\59} & \makecell{60\\-\\63} & \makecell{64\\-\\67} & \makecell{68\\-\\71} & \makecell{72\\-\\75} & \makecell{76\\-\\79} & \makecell{80\\-\\83} \\
\hline
Marks & 0& 1 & 2 & 3 & 4 & 5 & 6& 7& 8 & 9 & 10 & 11 & 12 & 13 & 14 &15 & 16 & 17 & 18 & 19 & 20 \\
\hline
\end{tabular}
}
\end{document}
这些分值对于所有考试都是不同的(在这个例子中,最大分数是 83,但也可以是任何其他数字),而分数总是在 0 到 20 之间。因此,表格中的第二行应该是固定的,列数也应该是固定的。我想根据最大数字动态填充第一行,因此应该以某种方式在 for 循环中填充第一行中的每个单元格。我该如何实现呢?
答案1
在表格尺寸固定的情况下,您可以在每个单元格中设置多个公式来定义范围。下面我定义了\lrange{<num>}
并\urange{<num>}
指定了l
ower 和u
pper 范围块(从 0 到 20)以及xfp
用于计算相应的下限/上限值。测试的总分/m
最高分s
核心保存在里面\ms
(但可以将其更改为自动获取测试的总分)。
\documentclass[addpoints,12pt]{exam}
\usepackage{booktabs,xfp,array}
\newcommand{\ms}{83}
\newcommand{\passfail}{10}
\newcommand{\lrange}[1]{%
\ifnum#1<\passfail
%\itshape% fail
\else
\bfseries% pass
\fi
\fpeval{#1 > 0 ? floor((\ms / 21) * #1 + 1, 0) : 0}
}%
\newcommand{\urange}[1]{%
\ifnum#1<\passfail
%\itshape% fail
\else
\bfseries% pass
\fi
\fpeval{floor((\ms / 21) * (#1 + 1), 0)}%
}
\begin{document}
\begingroup
\small
\setlength\tabcolsep{0.25em}
\renewcommand{\arraystretch}{1}% for the vertical padding
\begin{tabular}{ r *{21}{ w{c}{1em} } }
\toprule
& \multicolumn{21}{c}{Point range on this test (\textbf{pass} / fail)} \\
\cmidrule{2-22}
from & \lrange{0} & \lrange{1} & \lrange{2} & \lrange{3} & \lrange{4} & \lrange{5} & \lrange{6} & \lrange{7} & \lrange{8} & \lrange{9} & \lrange{10} &
\lrange{11} & \lrange{12} & \lrange{13} & \lrange{14} & \lrange{15} & \lrange{16} & \lrange{17} & \lrange{18} & \lrange{19} & \lrange{20} \\[\dimexpr-\normalbaselineskip+0.7em]
& -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- & -- \\[\dimexpr-\normalbaselineskip+0.8em]
to & \urange{0} & \urange{1} & \urange{2} & \urange{3} & \urange{4} & \urange{5} & \urange{6} & \urange{7} & \urange{8} & \urange{9} & \urange{10} &
\urange{11} & \urange{12} & \urange{13} & \urange{14} & \urange{15} & \urange{16} & \urange{17} & \urange{18} & \urange{19} & \bfseries\ms \\
\midrule
Marks & 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 & 15 & 16 & 17 & 18 & 19 & 20 \\
\bottomrule
\end{tabular}
\endgroup
\end{document}
当然,我对格式进行了一些调整,您可以将其恢复为您自己的风格。
答案2
编辑(1): 第一次尝试时我错过了问点。
使用@Werner 答案中提出的想法来tabularray
打包表代码可以是:
编辑(2):
在计算点范围时(现在)使用包colnum
中定义的。tabularray
编辑(3):
任意范围\fpeval{ceil(83/21*(\thecolnum-2)}
(因为第一个范围从 0 开始)并结束于,\fpeval{floor(83/21*(\thecolnum-1))-1}
但最后一个范围除外,它以最大点数结束(\mr
)。考虑到这一点,计算算法为:
\newcommand{\mr}{42} % <--- maximum of ranges
\newcommand{\range}%
{\fpeval{ceil(\mr/21*(\thecolnum-2))}
\\---\\
\ifnum\thecolnum=22%
\vphantom{i}\mr
\else
\vphantom{i}\fpeval{ceil(\mr/21*(\thecolnum-1))-1}%
\fi}
其中最大范围值。从算法可以看出,当等于或大于 42 时,\mr
它是有意义的。\mr
完整的 MWE 是:
\documentclass[12pt]{exam}
\usepackage{xfp}
\newcommand{\mr}{83}
\newcommand{\range}%
{\fpeval{ceil(\mr/21*(\thecolnum-2))}
\\---\\
\ifnum\thecolnum=22%
\vphantom{i}\mr
\else
\vphantom{i}\fpeval{ceil(\mr/21*(\thecolnum-1))-1}%
\fi}
\usepackage{tabularray}
\begin{document}
\begin{table}[ht]
%\small
\begin{tblr}{hlines,
vline{1-11}={solid}, vline{12}={1pt}, vline{13-Z}={solid},
colspec = {@{\,}Q[l,m, wd=1.3cm]
*{21}{ X[c,m] }
},
colsep=0pt,
cell{1,2}{2-11} = {font=\linespread{0.5}\relax},
cell{1,2}{12-Z} = {font=\bfseries\linespread{0.5}\relax}
}
Points ranges & \range & \range & \range
& \range & \range & \range
& \range & \range & \range
& \range & \range & \range
& \range & \range & \range
& \range & \range & \range
& \range & \range & \range \\
Marks & 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8
& 9 & 10 & 11 & 12 & 13 & 14 & 15 & 16 & 17
& 18 & 19 & 20 \\
\end{tblr}
\end{table}
\end{document}