答案1
原帖的标题写着减法,但他/她的图片显示的是加法。我最初选择后者,但后来编辑成也执行减法。在附录,我已经开始实现小数的过程,此时为2位数加法。
减法
如果有人愿意这样称呼它的话,一个已知的缺陷就是差异将显示前导零。
使用\showdiff{<minuend>}{<subtrahend>}
。
这种方法使用我的stringstrings
包从被减数和减数中一次提取一列,从右边开始(stringstrings
使用 功能可以方便地$
表示字符串结尾字符的位置)。它会减去它们,但如果值为负,它会执行借位。如果被减数的值\borrowed
小于零,它会将其增加到 9 并设置一个\futureborrowed
标志以应用于下一列。然后,它会构造并保存\Longstack
这些列数字中的一个(包括借入或借出数字的任何数量),名称为\thediff
。
\savediff
然后,通过将最新的添加\thediff
到现有的前面,构建 中和的全局图景\savediff
。它丢弃每个加数的最后一位数字(使用\nextcolumn
),然后它递归返回并再次执行此操作。当它确定截断的被减数和减数都为零时,它会在 前面添加一个减号\savediff
并显示它。
\documentclass{article}
\usepackage{stringstrings,stackengine}
\newcommand\showdiff[2]{%
\let\savediff\relax%
\def\borrow{}%
\xdef\borrowed{0}%
\ifnum#1>32\relax\showdiffengine{#1}{#2}\else
{\ttfamily\Longstack[r]{#1\,{} \underline{-#2\,} {< 0\,}}}\fi
}
\newcommand\showdiffengine[2]{%
\xdef\opA{#1}%
\xdef\opB{#2}%
\lastdigits{\opA}{\opB}%
\ifnum\borrowed=1\relax\xdef\XdigA{\the\numexpr\digA-1}\else\xdef\XdigA{\digA}\fi%
\ifnum\XdigA<0\relax\xdef\XdigA{9}\xdef\futureborrowed{1}\else
\xdef\futureborrowed{0}\fi
\edef\coldiff{\the\numexpr\XdigA-\digB\relax}%
\ifnum\coldiff<0\relax%
\xdef\borrow{1}%
\edef\coldiff{\the\numexpr\borrow\XdigA-\digB\relax}%
\else
\xdef\borrow{}%
\fi
\ifnum\borrowed=0\relax%
\savestack{\thediff}{\ttfamily\Longstack[l]{%
\tiny\bllap[1.5\baselineskip]{\borrow} \XdigA{} \underline{\VdigB\kern3pt} %
\coldiff}}%
\else
\savestack{\thediff}{\ttfamily\Longstack[l]{%
\tiny\brlap[.7\baselineskip]{\borrow\the\numexpr\XdigA} \crossout{\digA} %
\underline{\VdigB\kern3pt} \coldiff}}%
\fi
\if\relax\borrow\relax\xdef\borrowed{0}\else\xdef\borrowed{1}\fi
\savestack{\savediff}{\thediff\savediff}%
\ifnum\futureborrowed>0\relax\xdef\borrowed{1}\xdef\fugureborrowed{0}\fi
\nextcolumn{\opA}{\opB}%
\ifnum\numexpr0\opA+0\opB>0\relax\showdiffengine{\opA}{\opB}%
\else
\Longstack{\underline{\ttfamily-\,} {}}\savediff\fi%
}
\newcommand\crossout[1]{\stackengine{0pt}{#1}{/}{O}{c}{F}{F}{L}}
\newcommand\lastdigits[2]{%
\substring[q]{#1}{$}{$}%
\xdef\digA{\thestring}%
\xdef\VdigA{\digA}\if0\digA\ifnum#1=0\relax\xdef\VdigA{~}\fi\fi%
\substring[q]{#2}{$}{$}%
\xdef\digB{\thestring}%
\xdef\VdigB{\digB}\if0\digB\ifnum#2=0\relax\xdef\VdigB{~}\fi\fi%
}
\newcommand\nextcolumn[2]{%
\substring[q]{#1}{1}{$-1}%
\xdef\opA{0\thestring}%
\substring[q]{#2}{1}{$-1}%
\xdef\opB{0\thestring}%
}
\begin{document}
\showdiff{567}{243}\qquad
\showdiff{37}{9}\qquad
\showdiff{135}{49}\qquad
\showdiff{2134}{49}\bigskip
\showdiff{107}{23}\qquad
\showdiff{100}{1}\qquad
\showdiff{1000}{999}\qquad
\showdiff{10}{70}\qquad\bigskip
\end{document}
2 学期加法
使用\showsum{<addend-1>}{<addend-2>}
。
此方法还会从每个加数中一次提取一列,从右侧开始。它将这些加数相加,提取总和的最右边的数字,并保存余数。然后,它构建并保存\Longstack
这些列数字(包括任何先前的余数)的 ,名称为\thesum
。
\savesum
然后,通过将最新的添加\thesum
到现有的前面,构建 中和的全局图景\savesum
。它丢弃每个加数的最后一位数字(使用\nextcolumn
),然后它递归返回并再次执行此操作。当它确定余数和截断的加数都为零时,它会在 前面添加一个加号\savesum
并显示它。
(注意:这里的宏\nextcolumn
和\lastdigits
宏与上面减法代码中使用的宏相同)
\documentclass{article}
\usepackage{stringstrings,stackengine}
\newcommand\showsum[2]{%
\xdef\remainder{0}%
\xdef\Vremainder{~}%
\let\savesum\relax%
\showsumengine{#1}{#2}%
}
\newcommand\showsumengine[2]{%
\xdef\opA{#1}%
\xdef\opB{#2}%
\lastdigits{\opA}{\opB}%
\edef\colsum{\the\numexpr\digA+\digB+0\remainder\relax}%
\substring[q]{\colsum}{$}{$}%
\savestack{\thesum}{\ttfamily\Longstack[l]{%
\tiny\brlap[.7\baselineskip]{\Vremainder} \VdigA{} \underline{\VdigB\,} \thestring}}%
\substring[q]{\colsum}{1}{$-1}%
\xdef\remainder{\thestring}%
\if\relax\remainder\relax\xdef\Vremainder{}\else\xdef\Vremainder{\remainder}\fi%
\savestack{\savesum}{\thesum\savesum}%
\nextcolumn{\opA}{\opB}%
\ifnum\numexpr0\opA+0\opB+0\remainder>0\relax\showsumengine{\opA}{\opB}\else
\Longstack{\underline{\ttfamily+\,} {}}\savesum\fi%
}
\newcommand\lastdigits[2]{%
\substring[q]{#1}{$}{$}%
\xdef\digA{\thestring}%
\xdef\VdigA{\digA}\if0\digA\ifnum#1=0\relax\xdef\VdigA{~}\fi\fi%
\substring[q]{#2}{$}{$}%
\xdef\digB{\thestring}%
\xdef\VdigB{\digB}\if0\digB\ifnum#2=0\relax\xdef\VdigB{~}\fi\fi%
}
\newcommand\nextcolumn[2]{%
\substring[q]{#1}{1}{$-1}%
\xdef\opA{0\thestring}%
\substring[q]{#2}{1}{$-1}%
\xdef\opB{0\thestring}%
}
\begin{document}
\showsum{14}{7}\qquad
\showsum{56}{98}\qquad
\showsum{9236}{895}\qquad
\showsum{9236}{825}\bigskip
\showsum{9236}{455}\qquad
\showsum{98669}{985}\qquad
\showsum{98069}{905}
\end{document}
有 3 个加数的版本
使用大写“S”,\Showsum{<addend-1>}{<addend-2>}{<addend-3>}
\documentclass{article}
\usepackage{stringstrings,stackengine}
\newcommand\Showsum[3]{%
\xdef\remainder{0}%
\xdef\Vremainder{~}%
\let\savesum\relax%
\Showsumengine{#1}{#2}{#3}%
}
\newcommand\Showsumengine[3]{%
\xdef\opA{#1}%
\xdef\opB{#2}%
\xdef\opC{#3}%
\Lastdigits{\opA}{\opB}{\opC}%
\edef\colsum{\the\numexpr\digA+\digB+\digC+0\remainder\relax}%
\substring[q]{\colsum}{$}{$}%
\savestack{\thesum}{\ttfamily\Longstack[l]{%
\tiny\brlap[.7\baselineskip]{\Vremainder} \VdigA{} \VdigB{} \underline{\VdigC\,} %
\thestring}}%
\substring[q]{\colsum}{1}{$-1}%
\xdef\remainder{\thestring}%
\if\relax\remainder\relax\xdef\Vremainder{}\else\xdef\Vremainder{\remainder}\fi%
\savestack{\savesum}{\thesum\savesum}%
\Nextcolumn{\opA}{\opB}{\opC}%
\ifnum\numexpr0\opA+0\opB+0\opC+0\remainder>0\relax%
\Showsumengine{\opA}{\opB}{\opC}\else
\Longstack{\underline{\ttfamily+\,} {}}\savesum\fi%
}
\newcommand\Lastdigits[3]{%
\substring[q]{#1}{$}{$}%
\xdef\digA{\thestring}%
\xdef\VdigA{\digA}\if0\digA\ifnum#1=0\relax\xdef\VdigA{~}\fi\fi%
\substring[q]{#2}{$}{$}%
\xdef\digB{\thestring}%
\xdef\VdigB{\digB}\if0\digB\ifnum#2=0\relax\xdef\VdigB{~}\fi\fi%
\substring[q]{#3}{$}{$}%
\xdef\digC{\thestring}%
\xdef\VdigC{\digC}\if0\digC\ifnum#3=0\relax\xdef\VdigC{~}\fi\fi%
}
\newcommand\Nextcolumn[3]{%
\substring[q]{#1}{1}{$-1}%
\xdef\opA{0\thestring}%
\substring[q]{#2}{1}{$-1}%
\xdef\opB{0\thestring}%
\substring[q]{#3}{1}{$-1}%
\xdef\opC{0\thestring}%
}
\begin{document}
\Showsum{16}{7}{39}\qquad
\Showsum{898}{7}{439}\qquad
\Showsum{898032}{70405}{40309}\qquad
\Showsum{7040}{898032}{4030}
\end{document}
附录
以下是自动处理小数或整数的 2 位数加法:
\documentclass{article}
\usepackage{stringstrings,stackengine}
%%%%%% stringstrings BUG FIX (MISSING %)
\makeatletter
\renewcommand\testmatchingchar[3]{%
\setbox0=\hbox{%
\substring[e]{#1}{#2}{#2}\+%
\isnextbyte[q]{\EscapeChar}{#3}%
\if T\theresult%
\isnextbyte[q]{\EscapeChar}{\thestring}%
\if T\theresult%
\edef\@testcode{\expandafter\@DiscardNextChar\expandafter{#3}}%
\edef\@teststring{\@DiscardNextChar{\thestring}}%
\if \@teststring\@testcode\matchingchartrue\else\matchingcharfalse\fi
\else
\global\matchingcharfalse%
\fi
\else
\if \thestring#3\global\matchingchartrue\else\global\matchingcharfalse\fi
\fi}%
\?}
\makeatother
%%%%%
\edef\decchar{.}
\newcounter{digits}
\newcounter{decrements}
\newcommand\showsum[2]{%
\setcounter{digits}{0}%
\xdef\remainder{0}%
\xdef\Vremainder{~}%
\let\savesum\relax%
\whereischar[q]{#1}{\decchar}%
\xdef\locA{\theresult}%
\whereischar[q]{#2}{\decchar}%
\xdef\locB{\theresult}%
\ifnum\numexpr\locA+\locB=0\relax%
\def\decloc{-1}%
\showsumengine{#1}{#2}%
\else
\ifnum\locA=0\relax%
\xdef\numA{#1\decchar}%
\whereischar[q]{\numA}{\decchar}%
\xdef\locA{\theresult}%
\else
\xdef\numA{#1}%
\fi
\stringlength[q]{\numA}%
\xdef\lenA{\theresult}%
\substring[q]{\numA}{1}{\numexpr\locA-1\relax}%
\xdef\preA{\thestring}%
\substring[q]{\numA}{\numexpr\locA+1\relax}{$}%
\xdef\postA{\thestring}%
\ifnum\locB=0\relax%
\xdef\numB{#2\decchar}%
\whereischar[q]{\numB}{\decchar}%
\xdef\locB{\theresult}%
\else
\xdef\numB{#2}%
\fi
\stringlength[q]{\numB}%
\xdef\lenB{\theresult}%
\substring[q]{\numB}{1}{\numexpr\locB-1\relax}%
\xdef\preB{\thestring}%
\substring[q]{\numB}{\numexpr\locB+1\relax}{$}%
\xdef\postB{\thestring}%
\def\decsA{\numexpr\lenA-\locA}%
\def\decsB{\numexpr\lenB-\locB}%
\ifnum\decsA=\decsB%
\xdef\decloc{\decsA}%
\else\ifnum\decsA>\decsB%
\xdef\decloc{\decsA}%
\setcounter{decrements}{\the\numexpr\decsA-\decsB}%
\paddecimal{\postB}%
\else%
\xdef\decloc{\decsB}%
\setcounter{decrements}{\the\numexpr\decsB-\decsA}%
\paddecimal{\postA}%
\fi%
\fi%
\showsumengine{\preA\postA}{\preB\postB}%
\fi%
}
\newcommand\paddecimal[1]{%
\xdef#1{#1 }%
\addtocounter{decrements}{-1}%
\ifnum\value{decrements}>0\relax\paddecimal{#1}\fi%
}
\newcommand\showsumengine[2]{%
\ifnum\value{digits}=\decloc\relax\savestack\savesum{%
\Longstack{. \underline{.} .}\savesum}\fi
\stepcounter{digits}%
\xdef\opA{#1}%
\xdef\opB{#2}%
\lastdigits{\opA}{\opB}%
\edef\colsum{\the\numexpr\digA+\digB+0\remainder\relax}%
\substring[q]{\colsum}{$}{$}%
\savestack{\thesum}{\ttfamily\Longstack[l]{%
\tiny\brlap[.7\baselineskip]{\Vremainder} \VdigA{} \underline{\VdigB\,} \thestring}}%
\substring[q]{\colsum}{1}{$-1}%
\xdef\remainder{\thestring}%
\if\relax\remainder\relax\xdef\Vremainder{}\else\xdef\Vremainder{\remainder}\fi%
\savestack{\savesum}{\thesum\savesum}%
\nextcolumn{\opA}{\opB}%
\ifnum\numexpr0\opA+0\opB+0\remainder>0\relax\showsumengine{\opA}{\opB}\else
\Longstack{\underline{\ttfamily+\,} {}}\savesum\fi%
}
\newcommand\lastdigits[2]{%
\substring[q]{#1}{$}{$}%
\xdef\digA{\thestring}%
\xdef\VdigA{\digA}\if0\digA\ifnum#1=0\relax\xdef\VdigA{~}\fi\fi%
\substring[q]{#2}{$}{$}%
\xdef\digB{\thestring}%
\xdef\VdigB{\digB}\if0\digB\ifnum#2=0\relax\xdef\VdigB{~}\fi\fi%
}
\newcommand\nextcolumn[2]{%
\substring[q]{#1}{1}{$-1}%
\xdef\opA{0\thestring}%
\substring[q]{#2}{1}{$-1}%
\xdef\opB{0\thestring}%
\if.\thestring\nextcolumn{\opA}{\opB}\fi%
}
\begin{document}
\showsum{14}{7}\qquad
\showsum{56}{98}\qquad
\showsum{9236}{895}\qquad
\showsum{9236}{825}\bigskip
\showsum{9236}{455}\qquad
\showsum{98669}{985}\qquad
\showsum{98069}{905}\bigskip
\showsum{1.}{3.}\qquad
\showsum{1}{3.96}\qquad
\showsum{.2}{.94}\qquad
\showsum{121.24}{39.7}\qquad
\showsum{94.8}{121.2479}
\end{document}
附言:我感觉有个包裹正在过来……
答案2
您可以使用脫位包裹
\documentclass[border=5pt,tikz]{article}
\usepackage{xlop}
\begin{document}
\opadd{485,05}{178,4}
\opsub{245.25}{72.003}
\opsub[style=text]{72}{245}
\opsub[carrysub,lastcarry]{72}{245}
\end{document}