啊啊啊我的眼睛!

啊啊啊我的眼睛!

我对某些数学符号(例如 + 和 -)的间距不一致感到有些恼火,它们出现在字母(或符号)左侧时和出现在两个字母(或符号)之间时(如图所示)。这些间距不同有什么原因吗?有没有办法让它们始终相等,而不必每次在文本中出现时都手动执行此操作?

谢谢。在此处输入图片描述

答案1

全自动,得益于 LuaTeX。

\documentclass{article}
\usepackage{amsmath}
\usepackage{luacode}
\begin{luacode*}
local muglue_subtype
do
    for num, name in pairs(node.subtypes(node.id("glue"))) do
        if name == "muglue" then
            muglue_subtype = num
            break
        end
    end
end
assert(muglue_subtype, "No such subtype!")

function table.contains(haystack, needle)
    for _, straw in next, haystack do
        if straw == needle then
            return true
        end
    end
    return false
end

local glue_fields = { "width", "stretch", "stretch_order", "shrink", "shrink_order" }

local function binordspacing(head,style,penalties)
    local cur = head
    local match = 0
    while cur do
        local subtype = node.subtypes(cur.id)[cur.subtype]
        if match == 0 and table.contains({"op", "bin", "rel", "open", "punct"}, subtype) then
            match = 1
        elseif match == 1 and subtype == "bin" then
            match = 2
        elseif match == 2 and subtype == "ord" then
            local binordspacing = tex.getmath("binordspacing", style)
            local n = node.new("glue", muglue_subtype)
            for _, field in ipairs(glue_fields) do
                n[field] = binordspacing[field]
            end
            head = node.insert_before(head, cur, n)
            match = 0
        else
            match = 0
        end
        cur = cur.next
    end
    return true
end

luatexbase.add_to_callback("pre_mlist_to_hlist_filter", binordspacing, "binordspacing")
\end{luacode*}
\begin{document}
\begin{equation*}
    \alpha = -p(-w_1-v_0) - g(w_1)
\end{equation*}

\begin{center}
    $\alpha = -p(-w_1-v_0) - g(w_1)$
\end{center}
\end{document}

在此处输入图片描述

啊啊啊我的眼睛!


在评论中,您提到您还想在左括号和减号之间留出空格(天哪,为什么?),所以我想出了一个更可配置的方法。这允许您在 TeX 不会考虑的地方插入随机空格(出于充分的理由)。

\documentclass{article}
\usepackage{amsmath}
\usepackage{luacode}
\begin{luacode*}
local muglue_subtype
do
    for num, name in pairs(node.subtypes(node.id("glue"))) do
        if name == "muglue" then
            muglue_subtype = num
            break
        end
    end
end
assert(muglue_subtype, "No such subtype!")

local glue = glue or {}
function glue.copy(src)
    local glue_fields = { "width", "stretch", "stretch_order", "shrink", "shrink_order" }
    local g = node.new("glue", muglue_subtype)
    for _, field in ipairs(glue_fields) do
        g[field] = src[field]
    end
    return g
end

local knuth_table = {
    ord   = { ord = "0"  , op = "1"  , bin = "(2)", rel = "(3)", open = "0"  , close = "0"  , punct = "0"  , inner = "(1)" },
    op    = { ord = "1"  , op = "1"  , bin = "*"  , rel = "(3)", open = "0"  , close = "0"  , punct = "0"  , inner = "(1)" },
    bin   = { ord = "(2)", op = "(2)", bin = "*"  , rel = "*"  , open = "(2)", close = "*"  , punct = "*"  , inner = "(2)" },
    rel   = { ord = "(3)", op = "(3)", bin = "*"  , rel = "0"  , open = "(3)", close = "0"  , punct = "0"  , inner = "(3)" },
    open  = { ord = "0"  , op = "0"  , bin = "*"  , rel = "0"  , open = "0"  , close = "0"  , punct = "0"  , inner = "0  " },
    close = { ord = "0"  , op = "1"  , bin = "(2)", rel = "(3)", open = "0"  , close = "0"  , punct = "0"  , inner = "(1)" },
    punct = { ord = "(1)", op = "(1)", bin = "*"  , rel = "(1)", open = "(1)", close = "(1)", punct = "(1)", inner = "(1)" },
    inner = { ord = "(1)", op = "1"  , bin = "(2)", rel = "(3)", open = "(1)", close = "0"  , punct = "(1)", inner = "(1)" }
}

local function subtype(n)
    if not n then
        return nil
    end
    return node.subtypes(n.id)[n.subtype]
end

local function traverse(head, style)
    for n in node.traverse(head) do
        if n.id == node.id("sub_mlist") then
            traverse(n.list, style)
        else
            if subtype(n) == "bin" then
                local undefined = false
                -- look at the previous
                local prevtype = subtype(n.prev)
                if knuth_table[prevtype] and knuth_table[prevtype].bin == "*" then
                    undefined = true
                    local g = glue.copy(tex.getmath(prevtype .. "binspacing", style))
                    head = node.insert_before(head, n, g)
                end
                -- look at the next
                local nexttype = subtype(n.next)
                if undefined or knuth_table.bin[nexttype] == "*" then
                    local g = glue.copy(tex.getmath("bin" .. nexttype .. "spacing", style))
                    head = node.insert_after(head, n, g)
                end
                undefined = false
            end
        end
    end
end

local function binordspacing(head,style,penalties)
    traverse(head, style)
    return true
end

luatexbase.add_to_callback("pre_mlist_to_hlist_filter", binordspacing, "binordspacing")
\end{luacode*}

% Add further abominations to this list
\Umathopenbinspacing\displaystyle=\thinmuskip
\Umathopenbinspacing\textstyle=\thinmuskip
\Umathbinordspacing\displaystyle=\thinmuskip
\Umathbinordspacing\textstyle=\thinmuskip

\begin{document}
\begin{equation*}
    \alpha = -p(-w_1-v_0) - g(w_1)
\end{equation*}

\begin{center}
    $\alpha = -p(-w_1-v_0) - g(w_1)$
\end{center}
\end{document}

在此处输入图片描述

答案2

你问,

这些间距不同的原因是什么?

确实有!你(重新)发现了-作为+或操作unary员之间的区别binary

如果两种类型的运算符的间距相同,您可能会对它们相同感到恼火。

本质上,您所观察到的是数百年精细数学排版的结果,它已经确定使一元和二元运算符周围的间距相同并不是最佳的。

下面是一元和二元运算符的间距规则应用的一些实际例子。

在此处输入图片描述

\documentclass{article}
\begin{document}      
\obeylines % just for this example               
``$-$'' and ``$+$'' treated as unary operators:
$\dots,-3,-2,-1,0,+1,+2,+3,\dots$
$-1 \ne +1$
\bigskip
``$-$'' and ``$+$'' treated as binary operators:
$\dots,{}-3,{}-2,{}-1,0,{}+1,{}+2,{}+3,\dots$ --- looks awful!
$1+1=2$ \quad $2-2=0$
\bigskip
Mixed use:
$-1=5-6$ \quad $-5+6=+1$
\end{document}

答案3

欢迎!这实际上是一个功能,而不是错误。第一个减号是一个符号,而第二个减号是一个二元运算符。如果您想要更大的间距,可以添加一个{}

\documentclass{article}
\usepackage{amsmath}
\begin{document}
\begin{align*}
 \alpha&=-p(-w_1-v0)-g(w_1)\\
 \alpha&={}-p(-w_1-v0)-g(w_1)\\
\end{align*}
\end{document}

在此处输入图片描述

但对我来说,将符号与运算符区别对待似乎更合理。

相关内容