這個問題導致了一個新的包:
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 包,但其中沒有任何關於來回轉換單位的內容。
編輯:根據約瑟夫賴特的評論,更多細節:要轉換的單位至少是重量、長度和時間(最後一個是可選的,但有利)。轉換應從標準公制(公斤、公尺、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
實施你的 hack 非常簡單:
\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 包
當我第一次寫這篇文章時,我說應該可以使用正確的方法來做到這一點pgf鍵。部分作為概念驗證,部分作為學習如何使用的練習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在每行的 '之後排版命令。
答案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 \FPeval
。時間就是新的小時數,然後是分鐘和 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}!
變成這樣: