我想格式化实数,这些实数是使用该包进行长时间计算的结果l3fp
,以便将其作为值输出到 PDF 对象中的键。格式化的数字在“ ”后最多应有 9 位数字.
,尾随零被修剪,并且没有指数部分。
\fp_round_places:Nn
和的组合\fp_to_tl:N
不会给出想要的结果,因为\fp_to_tl:N
如果它更紧凑的话,有时会留下一个具有指数部分的实数。
\my_format_num:n|x{<real number>}
因此,我自己编写了一个宏。它运行得很好,但我无法将结果保存到标记列表变量中。在这种情况下,我得到了 TeX 错误:
! Argument of \my_format_num:w has an extra }.
下面的代码是我目前所做的。我该如何改进它,以便将结果保存在 tl 变量中?
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \my_format_num:n|x{<real number without any exponent part>}
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% macro to format real numbers
%
% * to show at most 9 places after `.'
% * trailing zeros removed
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\cs_new:Nn\my_format_num:n{
\exp_after:wN\my_format_num:w#1000000000\q_stop
}
\cs_generate_variant:Nn\my_format_num:n{x}
\cs_new:Npn\my_format_num:w#1.#2\q_stop{
#1.\exp_after:wN\my_trim_places:w#2\q_stop
}
\cs_new:Npn\my_trim_places:w#1#2#3#4#5#6#7#8#9\q_stop{
\my_trim_zeros:x{\exp_after:wN\tl_head:w#9\q_stop#8#7#6#5#4#3#2#1}
}
\cs_new:Nn\my_trim_zeros:n{
\exp_after:wN\my_trim_zeros:w#1\q_stop
}
\cs_generate_variant:Nn\my_trim_zeros:n{x}
\cs_new:Npn\my_trim_zeros:w#1#2\q_stop{
\str_if_eq:nnTF{#1}{0}{
\int_compare:nNnTF{\tl_length:n{#2}}>{\c_one}{
\exp_after:wN\my_trim_zeros:w#2\q_stop
}{#2}
}{
\tl_reverse:n{#2}#1
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\fp_set:Nn\my_vara_fp{-1.234e-8}
\fp_set:Nn\my_varb_fp{123456789.987654321e-9}
\fp_set:Nn\my_varc_fp{1.234}
% result as expected: -0.000000012
$\fp_use:N\my_vara_fp\rightarrow\my_format_num:x{\fp_use:N\my_vara_fp}$\par
% result as expected: 0.123456789
$\fp_use:N\my_varb_fp\rightarrow\my_format_num:x{\fp_use:N\my_varb_fp}$\par
% result as expected: 1.234
$\fp_use:N\my_varc_fp\rightarrow\my_format_num:x{\fp_use:N\my_varc_fp}$\par
% cannot save result in tl var
% \tl_set:Nx\my_vara_tl{\my_format_num:x{\fp_use:N\my_vara_fp}}
\end{document}
\ExplSyntaxOff
答案1
有了足够新的expl3
(2012 年 7 月应该足够了),你可以做
\documentclass{article}
\usepackage{expl3, xparse}
\ExplSyntaxOn
\DeclareDocumentCommand { \myformat }{m}
{ \fp_to_decimal:n { round((#1),9) } }
\ExplSyntaxOff
\begin{document}
\myformat{3.4}
\myformat{1234.567891234567}
\myformat{3+4-7+1.23456e-5}
\end{document}
答案2
感谢 Bruno 的评论,我已经想出了一个可行的解决方案。顶级宏的语法略有变化。尽管如此,在l3fp
LaTeX3 包中添加具有类似 C 格式功能的函数将受到热烈欢迎!
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \my_format_num:N<tl var>
% <tl var> contains a real number without exponent part
% the contents of <tl var> will be overwritten with the result
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% contents of <tl var> is formatted
% * to show at most 9 places after `.'
% * trailing zeros removed
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\cs_new:Nn\my_format_num:N{
\tl_set:Nx#1{\exp_after:wN\my_format_num:w#1\q_stop}
}
\cs_new:Npn\my_format_num:w#1.#2\q_stop{
#1.\exp_after:wN\my_trim_places:w#2000000000\q_stop
}
\cs_new:Npn\my_trim_places:w#1#2#3#4#5#6#7#8#9\q_stop{
\my_trim_zeros:f{\exp_after:wN\tl_head:w#9\q_stop#8#7#6#5#4#3#2#1}
}
\cs_new:Nn\my_trim_zeros:n{
\exp_after:wN\my_trim_zeros:w#1\q_stop
}
\cs_generate_variant:Nn\my_trim_zeros:n{f}
\cs_new:Npn\my_trim_zeros:w#1#2\q_stop{
\str_if_eq:nnTF{#1}{0}{
\int_compare:nNnTF{\tl_length:n{#2}}>{\c_one}{
\exp_after:wN\my_trim_zeros:w#2\q_stop
}{#2}
}{
\tl_reverse:n{#2}#1
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\fp_set:Nn\my_vara_fp{-1.234e-8}
\fp_set:Nn\my_varb_fp{123456789.987654321e-9}
\fp_set:Nn\my_varc_fp{1.234}
\tl_set:Nx\my_vara_tl{\fp_use:N\my_vara_fp}
\my_format_num:N\my_vara_tl
\tl_set:Nx\my_varb_tl{\fp_use:N\my_varb_fp}
\my_format_num:N\my_varb_tl
\tl_set:Nx\my_varc_tl{\fp_use:N\my_varc_fp}
\my_format_num:N\my_varc_tl
\my_vara_tl\par
\my_varb_tl\par
\my_varc_tl
\end{document}
\ExplSyntaxOff