![使用“印度数字系统”将数字转换为文字,例如 111 = 一百一十一](https://linux22.com/image/381942/%E4%BD%BF%E7%94%A8%E2%80%9C%E5%8D%B0%E5%BA%A6%E6%95%B0%E5%AD%97%E7%B3%BB%E7%BB%9F%E2%80%9D%E5%B0%86%E6%95%B0%E5%AD%97%E8%BD%AC%E6%8D%A2%E4%B8%BA%E6%96%87%E5%AD%97%EF%BC%8C%E4%BE%8B%E5%A6%82%20111%20%3D%20%E4%B8%80%E7%99%BE%E4%B8%80%E5%8D%81%E4%B8%80.png)
请问是否有使用 LaTeX 将数字排版为文字的方法。我创建了一张发票,我想将发票金额转换为文字。例如,“1,23,456.00”应排版为“One Lakh Twenty Three Thousand Four Hundred Fifty Six Only”。
提前谢谢啦~
答案1
答案2
(更新了答案,以允许数字中的小数部分以及非常大的数字(> 10 ^ 12))
(2019 年 9 月:更新了 Lua 代码中的 1 行,使其在基于 Lua 5.3 的 LuaTeX 版本下正常工作——它有一个单独的数字输入类型integer
。)
这是一个基于 LuaLaTeX 的解决方案,它用文字表达数字,同时使用所谓的印度数字系统.该系统使用倍数十万(10^5
),千万卢比(10^7
), 和十亿卢比(10^12
) 代替百万,十亿, 和兆来表示大数。
代码由 2 个 Lua 实用函数组成,一个 Lua 函数名为num2word
,另一个 LaTeX 宏名为\numtoword
,后者只是该函数的前端或“包装器” num2word
。 的参数\numtoword
必须是正数或根据 Lua 语法的通常规则求值为正数的表达式,例如1+1+1
、2e7
和3*10^5
。
逗号不是允许在 的输入中使用\numtoword
。即,不要写\num2word{1,000,000}
(“西方”系统) 或\numtoword{10,00,000}
(“印度”系统),而应写\num2word{1000000}
或\num2word{1e6}
。
如果数字包含小数部分,小数部分将自动四舍五入为 2 位数字。我熟悉的大多数现代货币都包含“分”部分,即小数部分是 的倍数0.01
。
如果数字小于 1 十万 (10^5),并且数字的小数部分等于 0,则将后缀“Only”附加到字符串中;如果数字的小数部分不为零,则将附加其等价单词(使用“百分位”)。最后,如果数字恰好等于 0,或者是一个大整数 (>=1e5),且仅由十万、千万和/或十千万组成(但没有万位部分),则不附加“Only”后缀。
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{geometry} % optional
\usepackage{fancyvrb} % for "\Verb" macro
\usepackage{numname} % for "\NumToName" macro
% Modify some of the macros of the 'numname' package
\renewcommand*{\namenumbercomma}{ } % default: "{, }"
\renewcommand*\tensunitsep{ } % default: "{-}"
\renewcommand*{\namenumberand}{ } % default: "{ and }"
\usepackage{luacode} % for "luacode" environment
\begin{luacode}
-- Utility function: Round number to nearest integer
function math.round ( x )
return x>=0 and math.floor(x+0.5) or math.ceil(x-0.5)
end
-- Typeset non-integer part of the number
function displaycents ( c , flag )
-- value of 'flag' can be either '1' or '0'
if flag==1 then
if c==0 then
tex.sprint ( " Only" )
elseif c==1 then
tex.sprint ( " and One Hundreth" )
else
tex.sprint ( " and \\NumToName{" .. c .. "} Hundreths" )
end
elseif flag==0 then
if c==0 then
tex.sprint ( "Zero" )
elseif c==1 then
tex.sprint ( "One Hundreth" )
else
tex.sprint ( "\\NumToName{" .. c .. "} Hundreths" )
end
end
end
-- 'num2name' is the main lua function
function num2name ( n )
local cents, lakhcrore, crore, lakh, rem
-- Retrieve decimal and integer parts of 'n'
cents = math.round ( 100 * ( n-math.floor(n) ) )
n = math.floor ( n ) -- integer part
-- calculate number of lakh crore, crore, lakh, and rem
lakhcrore = math.floor ( n / 1e12 ) -- lakh crore
crore = math.floor ( (n % 1e12) / 1e7 )-- crore
lakh = math.floor ( (n % 1e7) / 1e5 ) -- lakh
rem = math.floor ( n % 1e5 ) -- remainder % modified 2019-09-23
if n>0 then -- number >= 1.00
if lakhcrore>0 then
if crore==0 then
tex.sprint ( "\\NumToName{" .. lakhcrore .. "} Lakh Crore" )
else
tex.sprint ( "\\NumToName{" .. lakhcrore .. "} Lakh" )
end
if crore>0 or lakh>0 or rem>0 then tex.sprint (" ") end
end
if crore>0 then
tex.sprint ( "\\NumToName{" .. crore .. "} Crore" )
if lakh>0 or rem>0 then tex.sprint (" ") end
end
if lakh>0 then
tex.sprint ( "\\NumToName{" .. lakh .. "} Lakh" )
if rem>0 then tex.sprint (" ") end
end
if rem>0 then
tex.sprint ( "\\NumToName{" .. rem .. "}" )
-- display fractional part ("cents")
displaycents ( cents , 1 )
end
else -- 0 <= number <= 0.99
displaycents ( cents , 0 )
end
end
\end{luacode}
%% LaTeX wrapper macro:
\newcommand\numtoword[1]{\directlua{num2name(#1)}}
\begin{document}
\noindent
\begin{tabular}{@{}ll@{}}
\Verb:10^5: & \numtoword{10^5} \\
\Verb:2e7: & \numtoword{2e7} \\
\Verb:3e12: & \numtoword{3e12} \\
\Verb:6789e8: & \numtoword{6789e10} \\
\Verb:456e5: & \numtoword{456e5} \\
\Verb:123456:& \numtoword{123456} \\
\Verb:123456.78: & \numtoword{123450+6.78} \\
\Verb:1: & \numtoword{1} \\
\Verb:0: & \numtoword{0} \\
\Verb:0.01: & \numtoword{0.01} \\
\Verb:0.51: & \numtoword{0.51} \\
\end{tabular}
\end{document}