这个问题导致了一个新的方案的出现:
smartunits
我目前正在撰写一份文件,希望能够发布给欧洲和美国的读者。问题在于,像往常一样,英制单位和公制单位之间的选择。
文本不是科学的,也不是为科学读者准备的,所以我不能简单地从头到尾使用公制单位。由于许多单位都隐藏在文本中,因此找到它们并更改它们非常麻烦(即使使用隐藏的注释作为引导标志)。
我正在寻找一种兼具两全其美的方法。我正在寻找一种可以将所有公制单位转换为英制单位并反之亦然的方法。理想的方案如下:
\usepackage{smart_unit_package}
\smart_unit_convert{imperial}
...
\begin{document}
Oscar Wilde's height is said to have been \smart_unit{1.91}{meter}.
\end{document}
希望结果如下:
Oscar Wilde's height is said to have been 6'3''
其背后的想法是可以从序言中控制单位,而不必改变文本。
是否有这样的可用包,或者是否可以轻松创建我自己的解决方案(我不太擅长编码,甚至从未尝试过用 Tex 编写任何东西)?
我看了一下 siunitx 包,但其中没有关于来回转换单位的内容。
编辑:根据 Joseph Wright 的评论,还有更多细节:要转换的单位至少是重量、长度和时间(最后一个是可选的,但很方便)。转换应从标准公制(千克、米、24:00 格式)转换为英制(磅、英尺、12 AM/PM 格式)。
如果我个人正在编写一个包,我可能会允许使用某些命令标志(例如:公里应该转换为英里,而不是千英尺),并且身高(比如 189 厘米)应该转换为 6'2'',而不是“2 码”。
我意识到,要针对每种可能的情况(人体高度、山峰高度、小距离、大距离等)正确计算这个数字有些复杂(主要是因为英制单位制有些奇怪)。至于准确性:由于它不是为科学读者编写的,因此四舍五入到小数点是可以的。例如:1 米可以轻松转换为 3 英尺,即使它不是非常精确。当然,如果需要更高的准确性,则需要一个四舍五入点。
第二次编辑:我认为一个简单的技巧也可能有效(即使它不是非常优雅),是在乳胶中定义两个单词的方法。例如:
Oscar Wilde's height is said to have been \twowords{191cm}{6'3''}.
在序言中可以选择选择哪一个。这将迫使用户自己转换所有内容,但至少可以方便地在单位之间进行切换。
答案1
实施你的黑客攻击非常简单:
\newif\ifMetric\Metrictrue% metric by default
\newcommand\MyUnit[2]{\ifMetric #1\else #2\fi}% \MyUnits{metric}{imperial}
然后,您只需\MyUnit{191cm}{6'3''}
在文档中轻松使用 并随时使用 和 在公制和英制之间进行\Metrictrue
切换\Metricfalse
。
这是一个完整的例子(粗略地使用了国际单位制根据评论中的要求):
\documentclass{article}
\usepackage{SIunits}
\newif\ifMetric\Metrictrue% metric by default
\newcommand\MyUnit[2]{\ifMetric #1\else #2\fi}% \MyUnits{metric}{imperial}
\begin{document}
Metric: \MyUnit{191 \centi\meter}{$6'3''$}
\Metricfalse Imperial: \MyUnit{191 \centi\meter}{$6'3''$}
\Metrictrue Metric: \MyUnit{191 \centi\meter}{$6'3''$}
\end{document}
输出:
编辑:smartunits 包
当我第一次写这篇文章时,我说过应该可以使用鍵盤. 部分作为概念验证,部分作为学习如何使用pgfkeys
,现在有一个智能单元用于公制和英制单位之间转换的包。
以下是 MWE:
\documentclass{article}
\usepackage{smartunits}
\usepackage{xcolor}
\usepackage{listings}\lstset{language=[LaTeX]TeX}
\lstset{language=[LaTeX]TeX,
texcsstyle=*\bfseries\color{blue},
keywordstyle=\color{blue},
commentstyle=\color{brown},
morekeywords={SmartUnit,SmartUnitSettings,sisetup},
}
\begin{document}
\begin{lstlisting}[texcl]
\SmartUnitSettings{metric imperial, places=1}
\SmartUnit{km=100.0,figures=1} % \SmartUnit{km=100.0,figures=1}
\SmartUnit{miles=62.15,places=1} % \SmartUnit{miles=62.15,places=1}
\SmartUnit{cm=10} % \SmartUnit{cm=10}
\SmartUnit{celsius=20} % \SmartUnit{celsius=20}
\SmartUnit{miles=5.0, figures=1} % \SmartUnit{miles=5.0, figures=1}
\SmartUnit{miles=5.0,places=2} % \SmartUnit{miles=5.0, places=2}
\SmartUnit{hours=0, minutes=59} % \SmartUnit{hours=0, minutes=59}
\SmartUnit{hours=12, minutes=12} % \SmartUnit{hours=12, minutes=12}
\SmartUnit{kg=10.0, places=1} % \SmartUnit{kg=10.0, places=1}
\SmartUnit{pound=10.0,figures=1} % \SmartUnit{pound=10.0,figures=1}
\SmartUnit{l=10.0, places=1} % \SmartUnit{l=10.0, places=1}
\SmartUnit{L=10.0, places=1,uk} % \SmartUnit{L=10.0, places=1,uk}
\end{lstlisting}
\end{document}
输出结果如下:
(使用列表包让 LateX 排版%
每行 's 后的命令。)
答案2
为了完整起见,一个选择是在 LaTeX 中进行单位转换,使用类似 pgf/tikz 或FP。我个人认为这不是一个理想的解决方案,因为有很多边缘情况(例如,何时在米和公里之间转换,或者要四舍五入多少)。不过,对于非科学用途来说,它可能已经足够了。有了这一警告,下面是一个可能的实现。
首先,我们设置一个标志来在公制和英制单位之间进行选择。
\newif\ifmetric\metrictrue
然后,我们可以开始实现一个宏,根据此标志的状态在 24 小时制和 12 小时制之间切换。我们假设我们输入的是 24 小时制时间,并在必要时将其转换为 12 小时制。
\def\smarttime#1#2{%
\ifmetric%
#1:#2%
\else%
\ifnum#1>12%
\FPeval{\result}{trunc(#1 - 12:0)}%
\result:#2 PM%
\else%
#1:#2 AM%
\fi%
\fi%
}
基本上,它的作用是检查第一个参数(小时数)是否大于 12。如果是,则使用 fp 包\FPeval
从小时数中减去 12。然后时间就是新的小时数,后面是分钟数和 PM。否则,我们只需在时间末尾添加 AM。这实际上应该完全可以满足您的需求。
接下来,让我们进行两个单位之间的转换,比如公斤和磅。
\def\smartkilogram#1{%
\ifmetric%
#1 kg%
\else%
\FPeval{\result}{round(#1 * 2.204:1)}%
\result\ lbs%
\fi%
}
再次,我们只需进行数学运算\FPeval
并使用我们的标志在公制和英制单位之间切换。
米和英尺加英寸之间的转换稍微复杂一些,但与我们将公斤转换为磅并没有本质上的区别。
% Conditionally converts meters to miles/feet/inches
\def\smartmeter#1{%
% Use metric units (meters)
\ifmetric%
\FPeval{\result}{trunc(#1:0)}%
\ifnum\result>1000%
\FPeval{\result}{trunc(#1/1000:1)}%
\result\ km%
\else%
\FPeval{\result}{trunc(#1:2)}%
\result\ m%
\fi%
% Use imperial units (feet and inches)
\else
\FPeval{\result}{trunc((3.281 * #1):0)}%
\ifnum\result<5280%
\FPeval{\result}{(3.281 * #1)}%
\FPeval{\feet}{trunc((\result):0)}%
\FPeval{\inch}{trunc((12 * ((\result) - (\feet))):0)}%
\feet'\inch"%
\else
\FPeval{\feet}{trunc((\result):0)}%
\FPeval{\miles}{trunc((\feet / 5280):1)}%
\miles\ miles%
\fi%
\fi%
}
如果你也使用公里来工作,那么定义如下内容可能会更有意义:
\def\smartkilometer#1{\FPeval{\result}{trunc((#1 * 1000):0)}\smartmeter{\result}}
它的作用是将您提供的任何数字乘以 1000,并将其放入\smartmeter
宏中。它使用宏的名称 ( \smartmeter
vs \smartkilometer
) 来跟踪单位。
定义这些宏后,代码如下:
\subsection*{Metric Units}
\metrictrue
Oscar Wilde's height is said to have been \smartmeter{1.91}.\\
Five kilometers is \smartkilometer{5}.\\
It is \smarttime{9}{00}. Later it will be \smarttime{13}{30}.\\
That ostrich weights \smartkilogram{100}!
\subsection*{Imperial Units}
\metricfalse
Oscar Wilde's height is said to have been \smartmeter{1.91}.\\
Five kilometers is \smartkilometer{5}.\\
It is \smarttime{9}{00}. Later it will be \smarttime{13}{30}.\\
That ostrich weights \smartkilogram{100}!
变成这样: