我正在进行第二次尝试创建基本的高中因式分解工作表。
接下来要弄清楚如何拒绝不需要的零和一。
以下代码生成简单的三项式方程,但显示出两种不必要的行为。
- 当随机
\b
=时,它会产生不必要的平方差-\d
。我希望拒绝这些结果,然后简单地重新运行代码。 - 它打印系数 -1 和 1。
修复此问题最简单的方法是什么?
谢谢!
\documentclass{article}
\usepackage[margin=1.2cm]{geometry}
\usepackage{ifthen}
\usepackage{multicol}
\setlength{\columnsep}{1.5cm}
\usepackage{pgf}
\usepackage{pgffor}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\pgfmathsetseed{\number\pdfrandomseed}
% How to make sure that we don't get a difference of squares, i.e. if \b=-\c, then the middle term will be zero and it's a DOS.
\newcommand{\InitVariables}
{%
\pgfmathsetmacro{\b}{int(random(1,10)-11)}
\pgfmathsetmacro{\d}{int(random(1,10))}
\pgfmathsetmacro{\B}{int(\d+\b)}
\pgfmathsetmacro{\C}{int(\b*\d)}
}
\newcommand{\trinomial}
{%
\InitVariables
\((x\b)(x+\d)=\ifnum \B <0 x^2{\B}x\C \else x^2+{\B}x\C\fi\)
}
\newcommand{\ManyTrinomials}[1]
{%
\foreach \x in {1,2,3,...,#1}
{\trinomial \\}
}
\begin{document}
\ManyTrinomials{50}
\end{document}
答案1
要选择在范围内\b
且在范围内的\d
随机不同数字,我将使用\d
1..10
\d
-10,...,-1
\pgfmathsetmacro{\d}{int(random(1,10)}
\pgfmathsetmacro{\b}{int(random(1,9))}
现在\b
用-\b
if\b<\d
和-1-\b
else 替换。
对于系数的打印问题,您只需要另一个\ifnum
分支。事实上,您需要两个分支,因为-1x
您不想打印,而是想打印-x
。
这是经过这些修改的 MWE:
\documentclass{article}
\usepackage[margin=1.2cm]{geometry}
\usepackage{ifthen}
\usepackage{multicol}
\setlength{\columnsep}{1.5cm}
\usepackage{pgf}
\usepackage{pgffor}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\pgfmathsetseed{\number\pdfrandomseed}
% How to make sure that we don't get a difference of squares, i.e. if \b=-\c, then the middle term will be zero and it's a DOS.
\newcommand{\InitVariables}
{%
\pgfmathsetmacro{\d}{int(random(1,10)}
\pgfmathsetmacro{\b}{int(random(1,9))}
\ifnum\b<\d\pgfmathsetmacro{\b}{int(-\b)}%
\else\pgfmathsetmacro{\b}{int(-1-\b)}%
\fi
\pgfmathsetmacro{\B}{int(\d+\b)}
\pgfmathsetmacro{\C}{int(\b*\d)}
}
\newcommand{\trinomial}
{%
\InitVariables
\((x\b)(x+\d)=x^2 \ifnum\B<0\ifnum\B=-1-\else\B\fi\else+\ifnum\B>1\B\fi\fi x\C\)
}
\newcommand{\ManyTrinomials}[1]
{%
\foreach \x in {1,2,3,...,#1}
{\trinomial \\}
}
\begin{document}
\ManyTrinomials{50}
\end{document}
以及输出的随机快照:
根据您正在做的其他事情,编写一个通用宏来漂亮地打印多项式可能会更好。
编辑
这是一个带有\printpolynomial
“漂亮打印多项式”宏的版本。该宏采用逗号分隔的系数列表,因此
\printpolynomial{3,-2,1}% --> 3x^2-2x+1
请注意,该宏假定它处于数学模式,因此上述内容确实应该是$\printpolynomial{3,-2,1}$
。
为此,代码首先对系数进行一次试运行,以求得多项式的最大次数,称为\polydeg
——实际上,这是次数加一。然后,它再次遍历系数并打印它们。使用宏\plusseperator
来处理许多首项系数为 0 的烦人情况:
\printpolynomial{0,0,0,0,0,2,-2}%. -> 2x-2
在极端情况下,\printpolynomial{0,0,0,0,0}
会打印0
。除了担心系数1
和之外-1
,在处理多项式(如)时,指数和还会产生其他复杂情况\printpolynomial{1,1}
,其中常数项的系数确实需要打印。
作为最后的奖励,该宏接受一个可选参数,即行列式的名称。所以
\printpolynomial[y]{3,-4,2,1}%. --> 3y^3-4y^2+2y+1
如果打印指数增加的多项式,则可以稍微缩短宏;即以 的形式a_0+a_1x+a_2x^2+...+a_nx^n
。
修改后的代码如下:
\documentclass{article}
\usepackage[margin=1.2cm]{geometry}
\usepackage{ifthen}
\usepackage{multicol}
\setlength{\columnsep}{1.5cm}
\usepackage{pgf}
\usepackage{pgffor}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\pgfmathsetseed{\number\pdfrandomseed}
% usage: \printpolnomial[name of indeterminate]{a_n, ... , a_1, a_0}
\newcommand\printpolynomial[2][x]{%
% need to loop over #2 once to find the degree (actually, polydeg=degree+1)
\foreach \coeff [count=\polydeg, remember=\polydeg] in {#2} {}
\let\plusseperator\relax% as the leading coefficients may be zero use this instead of +
\foreach \coeff [count=\term, evaluate=\term as \pdeg using int(\polydeg-\term)] in {#2} {%
\ifnum\coeff=0\relax% do nothing
\else
\ifnum\coeff>0\relax%
\plusseperator% print a + if some terms have already appeared
\ifnum\coeff=1\relax%
\ifnum\pdeg=0\relax1\fi% print 1 if constant term
\else\coeff% print coefficient if it is greater than 1
\fi%
\else\ifnum\coeff<0%
\ifnum\coeff=-1\relax%
\ifnum\pdeg=0\relax-1\else-\fi% print -1 if constant term
\else\coeff% print \coeff
\fi%
\fi%
\fi%
\ifnum\pdeg=0\relax%
\else%
\ifnum\pdeg=1\relax #1\else {#1}^{\pdeg}\fi% print the power of #1 = x
\fi%
\gdef\plusseperator{+}% change \plusseperator to + as polynomial is non-zero
\fi%
}%
\ifx\plusseperator\relax 0\fi% zero polynomial
}
% How to make sure that we don't get a difference of squares, i.e.
% if \b=-\d, then the middle term will be zero and it's a DOS.
\newcommand{\InitVariables}
{%
\pgfmathsetmacro{\d}{int(random(1,10)}
\pgfmathsetmacro{\b}{int(random(1,9))}
\ifnum\b<\d\pgfmathsetmacro{\b}{int(-\b)}%
\else\pgfmathsetmacro{\b}{int(-1-\b)}%
\fi
\pgfmathsetmacro{\B}{int(\d+\b)}
\pgfmathsetmacro{\C}{int(\b*\d)}
}
\newcommand{\trinomial}
{%
\InitVariables
$(\printpolynomial{1,\b})(\printpolynomial{1,\d})
= \printpolynomial{1,\B,\C}$
}
\newcommand{\ManyTrinomials}[1]
{%
\foreach \x in {1,2,3,...,#1}
{\trinomial\\}
}
\begin{document}
$\printpolynomial{2,1,3,-2,0}$
$\printpolynomial{0,1,3,-2,0}$
$\printpolynomial{0,0,0,0,0}$
\ManyTrinomials{50}
\end{document}
答案2
sagetex
如果你愿意使用文档包,你可以使编码变得更容易这里。除了计算机代数系统的计算能力之外,您还可以通过 latex() 命令轻松编写 Python 命令,甚至内置命令来使输出变得漂亮。下面包含 latex(factor(poly)) 的代码行告诉 Sage 对创建的多项式进行因式分解,并以 LaTeX 代码表示结果。
\documentclass{article}%
\usepackage{sagetex}
\begin{document}
\begin{sagesilent}
x = var('x')
Problems = r"Factor each quadratic:\\ \begin{enumerate}"
for i in range(0,20):
r1 = Integer(randint(-10,10))
r2 = Integer(randint(-10,10))
while r1 == -r2:
r2 = Integer(randint(-10,10))
poly = expand((x-r1)*(x-r2))
Problems += r"\item $%s = %s$"%(latex(poly),latex(factor(poly)))
Problems += r"\end{enumerate}"
\end{sagesilent}
\sagestr{Problems}
\end{document}
习惯使用 Sage 和 sagemath 软件包可以让各种数学工作表变得更容易——Sage 可处理所有级别的数学您需要在计算机上本地安装 Sage 或免费SagemathCloud 帐户。
答案3
为了保险起见,这里有一个纯基于 LuaLaTeX 的解决方案。除了这个luacode
包之外,不需要其他包来生成所需的输出。
完整的 MWE:
% !TeX program = lualatex
\documentclass{article}
\usepackage{amsmath} % for 'align*' env.
%% Lua-side code
\usepackage{luacode}
\begin{luacode}
function trinom ( n ) -- n: # of iterations (integer)
local f1,f2,g1,g2,s1
for i=1,n do -- Repeat the following code 'n' times
-- f1 & f2: integers between -10 and 10, excl. 0
repeat f1=math.random(-10,10) until f1~=0
repeat f2=math.random(-10,10) until f2~=0 and f2~=-f1
-- Compute additive and multiplicative factors
g1 = f1+f2
g2 = string.format("%+i", f1*f2) -- store as string
-- Retrieve sign ("s1") of g1
if g1<0 then s1 = "-" else s1 = "+" end
g1 = tostring(math.abs(g1)) -- convert to abs. value
-- Special treatment if abs(g1)=="1"
if g1=="1" then g1 = "" end
-- Generate output
tex.sprint( "(x" .. string.format("%+i",f1) .. ")" ..
"(x" .. string.format("%+i",f2) .. ")" ..
"&= x^2" .. s1 .. g1 .. "x" .. g2 )
-- Insert line-break directive if not (yet) at last line
if n>1 and i<n then tex.sprint ( "\\\\" ) end
end -- end of 'for' loop
end -- end of 'trinom' function
\end{luacode}
%% TeX-side code
\newcommand\ManyTrinomials[1]{\directlua{trinom(#1)}}
\begin{document}
\allowdisplaybreaks
\begin{align*}
\ManyTrinomials{30} % 30 rows
\end{align*}
\end{document}
备注:如果你不想将方程式嵌入到align*
环境中,而只是想逐行打印出来,只需将块
tex.sprint( "(x" .. string.format("%+i",f1) .. ")" ..
"(x" .. string.format("%+i",f2) .. ")" ..
"&= x^2" .. s1 .. g1 .. "x" .. g2 )
到
tex.sprint( "(x" .. string.format("%+i",f1) .. ")" ..
"(x" .. string.format("%+i",f2) .. ")" ..
"= x^2" .. s1 .. g1 .. "x" .. g2 )
即省略符号&
。
答案4
这是一个expl3
版本,虽然我还没有翻译\foreach
这里的循环。我想这可能有意义,但我之前没有想到……
因此,再考虑一下,这里有一个不完全的expl3
版本:
\documentclass{article}
\usepackage[margin=1.2cm]{geometry}
\usepackage{enumitem,xparse}
\usepackage{multicol}
\setlength{\columnsep}{1.5cm}
\usepackage{pgffor}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\ExplSyntaxOn
\int_new:N \l_wcla_b_int
\tl_new:N \l_wcla_b_tl
\int_new:N \l_wcla_d_int
\tl_new:N \l_wcla_d_tl
\int_new:N \l_wcla_B_int
\tl_new:N \l_wcla_B_tl
\int_new:N \l_wcla_C_int
\tl_new:N \l_wcla_C_tl
\cs_new_protected_nopar:Nn \wcla_init_variables:
{
\int_zero:N \l_wcla_b_int
\int_zero:N \l_wcla_d_int
\int_do_while:nNnn { \int_abs:n { \l_wcla_b_int } } = { \int_abs:n { \l_wcla_d_int } }
{
\int_set:Nn \l_wcla_b_int { \fp_eval:n { randint ( -10 , -1 ) } }
\int_set:Nn \l_wcla_d_int { \fp_eval:n { randint ( 1 , 10 ) } }
}
\int_set:Nn \l_wcla_B_int { \l_wcla_b_int + \l_wcla_d_int }
\int_compare:nNnTF { \l_wcla_B_int } < { 0 }
{
\tl_set:Nn \l_wcla_B_tl { \wcla_de_one:n {\l_wcla_B_int} }
}{
\tl_set:Nn \l_wcla_B_tl { + \wcla_de_one:n {\l_wcla_B_int} }
}
\int_set:Nn \l_wcla_C_int { \l_wcla_b_int * \l_wcla_d_int }
\tl_set:Nn \l_wcla_C_tl { \int_to_arabic:n {\l_wcla_C_int} }
\tl_set:Nn \l_wcla_b_tl { \int_to_arabic:n {\l_wcla_b_int} }
\tl_set:Nn \l_wcla_d_tl { \int_to_arabic:n {\l_wcla_d_int} }
}
\cs_new_protected_nopar:Nn \wcla_trinomial:
{
\group_begin:
\wcla_init_variables:
\(
( x \l_wcla_b_tl ) ( x + \l_wcla_d_tl ) = x^2 \l_wcla_B_tl x \l_wcla_C_tl
\)
\group_end:
}
\cs_new_protected_nopar:Nn \wcla_de_one:n
{
\int_case:nnF { #1 }
{
{ -1 } { - }
{ 1 } { }
}{
\int_to_arabic:n { #1 }
}
}
\NewDocumentCommand \trinomial { }
{
\wcla_trinomial:
}
\ExplSyntaxOff
\newcommand{\ManyTrinomials}[1]
{%
\begin{itemize}[label={},wide,noitemsep]
\foreach \x in {1,2,3,...,#1} {\item \trinomial}
\end{itemize}%
}
\begin{document}
\ManyTrinomials{50}
\end{document}