
Ich möchte einen Befehl erstellen, der für eine gegebene Ganzzahl n
vom Typ eine vereinfachte Quadratwurzel von setzt n
. Beispielsweise wird die Ausgabe von
\rsqrt{4}
\rsqrt{8}
\rsqrt{18}
\rsqrt{7}
wäre das gleiche wie das von
2
2\sqrt{2}
3\sqrt{2}
\sqrt{7}
wo \rsqrt{}
ist der betreffende Befehl.
Ich weiß, dass der Algorithmus ungefähr so aussehen würde
i = square root of n rounded down
while i > 0:
if n is divisible by i²:
simplification is i\sqrt{n/i²}
break loop
i = i - 1
%the simpification will always be found
%since every n is divisible by 1
wobei n
die gegebene Ganzzahl ist, i
die Zahl davor ist \sqrt
und n/i²
das Argument von ist \sqrt{...}
.
Aber ich habe keine Ahnung, wie ich das in Latex implementieren soll?
BEARBEITEN: Klargestellt, dass die Eingabezahl immer eine Ganzzahl sein wird.
Antwort1
Der Algorithmus in der Frage ist sehr ineffizient: außer natürlich, wenn die ursprüngliche Ganzzahl eine Quadratzahl ist.
Diese Antwort (in chronologischer Reihenfolge):
ein Ansatz mit Makros, der den einfachsten Faktorisierungsalgorithmus nachahmt,
ein erweiterbarer Ansatz unter Verwendung des Algorithmus wie in OP.aktualisieren
I
sehr peinlich, der Autor hatte den Algorithmus des OP nicht verstanden und nachdem er eine Vereinfachung wieI^2
divided gefunden hatteN
, ging er rekursiv vorN<-N/I^2
, ohne zu verstehen, dass der Algorithmus dort aufhören konnte. (Als blasse Entschuldigung hatte er zuerst den „Bottom-up“-Weg implementiert, der Rekursivität erfordert, im Gegensatz zum (weniger effizienten) „Top-down“-Weg.) Die Antwort wurde somit aktualisiert, Entschuldigung an alle großzügigen, vertrauensvollen frühen Up-Voter.Ich aktualisiere erneut (Entschuldigung), weil ich jetzt mehr von der Dokumentation gelesen habe und aus Effizienzgründen von auf
xintexpr.sty
umgestiegen bin (es ist keins verfügbar, daher ein Trick mit Minuszeichen). Ersteres generiert im Voraus die gesamte Zahlenliste ( bedeutet gekürzte Quadratwurzel in ), letzteres ist ein Iterator, der nichts im Voraus generiert. Darüber hinaus kann die erstere Syntax nur etwa Werte generieren ( hätte keine solche Einschränkung, würde aber trotzdem alles im Voraus generieren).i=sqrt(N)..1
i=-sqrt(N)++
--
floor(\sqrt{N})
sqrt
\xintiiexpr
5000
sqrt(N)..[-1]..1
eine erweiterbare Implementierung eines schnelleren Algorithmus (Typ Faktorisierung auf High-School-Niveau) wie in Ansatz 1.
Ehrlich gesagt wären 2., 3. und sogar 1. wahrscheinlich besser geschrieben, wenn sie vollständig mit geschrieben würden, \numexpr
da ihr Anspruch, mit Zahlen größer als umzugehen, 2^31
etwas weit hergeholt ist. Bei einer Primzahl mit 10 Ziffern dauert es eine Weile, Zehntausende von Divisionen durchzuführen, um zu dem Schluss zu kommen, dass sie quadratfrei ist ... Implementierung 2. hat eine intrinsische Grenze auf , 2^62
weil die Quadratwurzel eine TeX-Zahl sein muss (aufgrund einer internen Konstruktion).
In 2. und 3. gehen wir mit rekursiven Sequenzen etwas über die Möglichkeiten der \xintexpr
Syntax hinaus. Die Notation ist etwas umständlich. Außerdem xintexpr.sty 1.2g
ist sie notwendig, da sie die relevante Syntax ändert.
- Schließlich (2017) füge ich auch den nur mit Numexpr erweiterbaren Ansatz ohne Paket hinzu.
Erster Ansatz (wir ändern den Algorithmus)
Damit will ich nicht sagen, dass dies ein einfaches Problem ist. Ein bisschen googeln zeigt, dass Mathematiker derzeit offenbar glauben, dass das Finden des quadratischen freien Radikals einer Ganzzahl genauso schwierig sein könnte wie die vollständige Faktorisierung:https://math.stackexchange.com/questions/171568/finding-the-radical-of-an-integerUndhttps://math.stackexchange.com/questions/14667/square-free-integers-factorization.
Hier ist ein Ansatz (mit Makros), der die einfachste Form des Faktorisierungsalgorithmus nachahmt.
Das Paket xintexpr
wird nur verwendet, um Eingaben wie 1e7
oder sogar Ausdrücke zu ermöglichen. Es lädt auch xinttools
, was in der Syntax verwendet wird.
Ansonsten werden alle Operationen mit Makros ausgeführt, die unter verfügbar sind xint
. Da wir im Beispiel fast nur mit Zahlen arbeiten, <2^31
könnten wir eine Variante verwenden, bei der alle Operationen eindeutig ausgeführt werden. \numexpr
Das wäre natürlich viel schneller.
Der Code verwendet \xintiiDivision
, wodurch Quotient und Rest gleichzeitig berechnet werden. Aus diesem Grund \xintAssign
wird verwendet, um sie in zwei Makros \A
und zu speichern \B
. Der Code prüft, ob \B
verschwindet, um die Teilbarkeit durch ein zu ermitteln Q=P^2
.
\documentclass[a4paper]{article}
\usepackage{geometry}
\usepackage{xintexpr}
\makeatletter
\def\Rsqrt@ {%
\let\Nrad\N
\def\Nroot {1}%
% we will always have original N = \Nrad times \Nroot^2
% first we check powers of 2
\def\P{2}%
\def\Q{4}% \Q is always square of \P
\xintloop
% try to divide \Nrad by 4. If possible, multiply \Nroot by 2
\xintAssign\xintiiDivision{\Nrad}{\Q}\to \A\B
\xintiiifZero{\B}
{\let\Nrad\A
\edef\Nroot{\xintiiMul{\Nroot}{\P}}%
\iftrue}
{\iffalse}%
\repeat
% try to divide \Nrad by 9=3^2, then by 25=5^2, etc...
% unfortunately we divide by all odd integers, but only odd prime
% integers would be really needed
\def\P{3}%
\xintloop
\edef\Q{\xintiiSqr{\P}}%
\xintiiifGt{\Q}{\Nrad}
{\iffalse}%
{\xintloop
\xintAssign\xintiiDivision{\Nrad}{\Q}\to \A\B
\xintiiifZero{\B}
{\let\Nrad\A
\edef\Nroot{\xintiiMul{\P}{\Nroot}}%
\iftrue}
{\iffalse}%
\repeat
\edef\P{\xintiiAdd{2}{\P}}%
\iftrue
}%
\repeat
% at this stage \N = \Nrad times \Nroot^2
% and \Nrad is square-free.
\xintiiifOne{\Nroot}{}{\Nroot}%
\xintiiifOne{\Nrad} {}{\sqrt{\Nrad}}%
}%
\newcommand* \Rsqrt[1]{%
\begingroup
\edef\N{\xinttheiexpr #1\relax}%
\xintiiifSgn \N
{\pm\edef\N{\xintiiAbs{\N}}\xintiiifOne\N{}{\Rsqrt@}i}
{0}
{\xintiiifOne \N{1}{\Rsqrt@}}
\endgroup
}
\makeatother
\usepackage{multicol}
\begin{document}
\parindent0pt\def\columnseprule{.4pt}%
% testing
% \begin{multicols}{4}
% \xintFor* #1 in {\xintSeq {10000}{10100}}\do
% {$\sqrt{#1}=\Rsqrt{#1}$\par}
% \end{multicols}
% $\Rsqrt{-10}, \Rsqrt{-1}, \Rsqrt{-16}$
$\Rsqrt {1e6}, \Rsqrt {1e7}, \Rsqrt{1e21}$
\pdfsetrandomseed 123456789
\begin{multicols}{3}
\xintiloop [1+1]
\edef\Z {\xinttheiiexpr
(\pdfuniformdeviate 1000)^2
*\pdfuniformdeviate 1000\relax }%
$\sqrt{\Z}=\Rsqrt{\Z}$\par
\ifnum\xintiloopindex<50
\repeat
\end{multicols}
\end{document}
Zweiter Ansatz (gleicher Algorithmus wie in OP, erweiterbare Implementierung)
Mit dem ursprünglichen Algorithmus. Hier definieren wir, was erweiterbar mit \ExtractRadical
zurückgibt . Ein nicht erweiterbarer Wrapper verwendet den schnelleren Ansatz oben erneut, um zu erzeugen und unterscheidet dabei zwischen Fällen mit negativem oder .A,B
N=A^2 B
\Rsqrt
A\sqrt{B}
N
N=0, 1
Ich habe Codekommentare hinzugefügt, um die Implementierung zu erklären. Eine frühere Version war sehr lahm (siehe oben in der Antwort) und erforderte zusätzlich, xintexpr 1.2g
was nicht mehr der Fall ist.
\documentclass[a4paper]{article}
\usepackage{geometry}
\usepackage{xintexpr}
% Aim: given N find largest I such as I^2 divides N.
% Then compute J=N/I^2 and print I\sqrt{J}.
% Algorithm: compute first truncated square root Imax of N.
% With I = Imax try to divide N by I^2, if it does not work
% repeat with I replaced by I-1 and so on.
% As soon as it works the seeked-for I has been found.
% **** Notice: embarrassingly the author of this answer initially continued
% **** the algorithm recursively with N<-N/I^2, which was very stupid, but
% **** explainable from the fact that he had implemented first another (much
% **** faster) algorithm which divided not from the top down, but from the
% **** bottom up.
% The code is far simpler now. And it does not require xintexpr 1.2g anymore,
% earlier versions of xintexpr.sty work, too.
% The iteration over i used Imax..1 syntax which requires Imax
% to be <2^31. Else we could use Imax..[-1]..1, but we don't
% really consider realistic to iterate over 2^31 or more values !
% After an update we use (-Imax)++ syntax; this also requires Imax<2^31.
\def\ExtractRadical #1{%
\xinttheiiexpr
subs(
% we return I, #1//I^2 where I is biggest integer such as I^2 divides #1.
(I, #1//I^2),
% The I is computed via the "seq" here. Theoretically this "seq"
% evaluates as many values as the last list indicates.
% But here we omit all i's such that i^2 does not divide #1
% and as soon as we have found one, we stop here and now by
% "break". We work topdown, at the worst I=1.
% The i=A..B syntax pre-generates all values, which is wasteful
% and limited to about at most 5000 values.
% I=seq((#1/:i^2)?{omit}{break(i)}, i=sqrt(#1)..1)
% On the contrary the N++ syntax does not pre-generate anything.
I=seq((#1/:i^2)?{omit}{break(-i)}, i=-sqrt(#1)++)
% There is currently no "n--" only "n++", thus we tricked with a minus sign.
)
\relax
}
\makeatletter
\def\Rsqrt@ {\expandafter\Rsqrt@@\romannumeral-`0\ExtractRadical\N,}
% The #2#3 trick is to get rid of a space after the comma
% because \ExtractRadical does \xinttheiiexpr which in case
% of comma separated values on output always inserts such a space.
% Naturally as the typesetting is in math mode the space is
% not a real problem (it is not a problem either in \xintiiifOne
% as here its argument is already expanded anyhow).
\def\Rsqrt@@ #1,#2#3,{\xintiiifOne{#1}{}{#1}\xintiiifOne{#2#3}{}{\sqrt{#2#3}}}
\newcommand* \Rsqrt[1]{%
\begingroup
\edef\N{\xinttheiexpr #1\relax}%
\xintiiifSgn \N
{\pm\edef\N{\xintiiAbs{\N}}\xintiiifOne\N{}{\Rsqrt@}i}
{0}
{\xintiiifOne \N{1}{\Rsqrt@}}
\endgroup
}
\makeatother
\usepackage{multicol}
\begin{document}
\parindent0pt\def\columnseprule{.4pt}%
% testing
\begin{multicols}{4}
\xintFor* #1 in {\xintSeq {10000}{10099}}\do
{$\sqrt{#1}=\Rsqrt{#1}$\par}
\end{multicols}
% $\Rsqrt{-10}, \Rsqrt{-1}, \Rsqrt{-16}$
$\Rsqrt {1e6}, \Rsqrt {1e7}$%,
% this one does not work because 10^10.5 > 2^31 causes an arithmetic
% overflow in the "sqrt(J)..1" part.
% It would not overflow with "sqrt(J)..[-1]..1"
% but then we can wait long time ...
% from 31622776601 downto
% 10000000000 that's a lot of iterations !
%$\Rsqrt{1e21}$
% The update uses n++ syntax, but this also requires abs(n) to be <2^31
% hence the same remark applies: a "Number too big" error is generated.
% Better actually than to wait the completion of 21622776601 iterations ;-)
% \stop
\pdfsetrandomseed 123456789
% we try with smaller numbers... 1000 replaced by 100...
\begin{multicols}{3}
\xintiloop [1+1]
\edef\Z {\xinttheiiexpr
(\pdfuniformdeviate 100)^2
*\pdfuniformdeviate 100\relax }%
$\sqrt{\Z}=\Rsqrt{\Z}$\par
\ifnum\xintiloopindex<51
\repeat
\end{multicols}
\end{document}
Dritter Ansatz: wieder der schnellere Algorithmus, aber erweiterbar.
Es wäre sinnvoller, dies à la \numexpr
but well zu codieren. Details im Codekommentar. Das Beispiel hat jetzt 51 zufällige Beispiele, und lustigerweise stellte sich das fehlende (aus dem ersten Ansatz) als zufälliges Quadrat heraus (mit dem Zufallsstartwert für den pdftex-Zufallszahlengenerator auf eingestellt 123456789
).
\documentclass[a4paper]{article}
\usepackage{geometry}
\usepackage{xintexpr}[2016/03/19]%
% needs xintexpr 1.2g due to
% - changed meaning of iter
% - shift by 1 in [L][n] syntax
% syntax \ExtractRadical {N or <integer expression>} expands to "A, B" with
% N=A^2 B, B square-free
% Algorithm:
% main variable a triple (P, I, J) where
% - always N = I^2 J
% - J's prime factors < P have multiplicity one.
% START: (2, 1, N)
% ITER: (P, I, J)
% Q=P^2
% is Q > J ?
% - yes: STOP(I, J)
% - no:
% does Q divide J ?
% - yes: I<-I*P, J<-J/Q and repeat until Q does not divide J
% - no; continue with (P+2, I, J). Except if P=2 then we go
% on with P=3.
% Also works with N=0 (produces 1, 0) and with N=1 (produces 1, 1)
%
\newcommand*\ExtractRadical [1]{%
\xinttheiiexpr
iter (2, 1, #1; % starting triple P=2, I=1, J=N
subs(subs(subs(subs(
% apart from Q=P^2, these substitutions are mainly because [@][n] syntax
% is cumbersome; and inefficient as it allows n to be itself a complicated
% expression, hence does some rather unneeded parsing here of n= 0, 1, 2.
% We really need some better syntax like iter(P=2, I=1, J=#1;...) and then
% work with P, I, J standing for the last values.
% Or at least something like subs(..., (Q, P, I, J)=(...)).
% (not yet with xintexpr 1.2g).
(Q>J)?
{break(I, J)}
{(J/:Q)?
{(n)?{P+2}{3}, I, J}
% must use parentheses here: ([@][1]). Else ]/: will confuse parser.
% I could have used again subs, but well.
{iter(P*I,J//Q;(([@][1])/:Q)?{break((n)?{P+2}{3},@)}
{(P*[@][0],([@][1])//Q)},e=1++)
}
}
, Q=P^2), P=[@][0]), I=[@][1]), J=[@][2]), n=0++)
\relax
}
\makeatletter
\def\Rsqrt@ {\expandafter\Rsqrt@@\romannumeral-`0\ExtractRadical\N,}
\def\Rsqrt@@ #1,#2,{\xintiiifOne{#1}{}{#1}\xintiiifOne{#2}{}{\sqrt{#2}}}
\newcommand* \Rsqrt[1]{%
\begingroup
\edef\N{\xinttheiexpr #1\relax}%
\xintiiifSgn \N
{\pm\edef\N{\xintiiAbs{\N}}\xintiiifOne\N{}{\Rsqrt@}i}
{0}
{\xintiiifOne \N{1}{\Rsqrt@}}
\endgroup
}
\makeatother
\usepackage{multicol}
\begin{document}
\parindent0pt\def\columnseprule{.4pt}%
% testing
% \xintFor* #1 in {\xintSeq {0}{50}}\do
% {\ExtractRadical {#1}\par}
% \ExtractRadical {128}
% \ExtractRadical {1024}
% \stop
% $\Rsqrt{5000}$
% \stop
% \begin{multicols}{4}
% \xintFor* #1 in {\xintSeq {10000}{10099}}\do
% {$\sqrt{#1}=\Rsqrt{#1}$\par}
% \end{multicols}
$\Rsqrt{-10}, \Rsqrt{-1}, \Rsqrt{-16}$
$\Rsqrt {1e6}, \Rsqrt {1e7}, \Rsqrt {1e21}$%,
\pdfsetrandomseed 123456789
\begin{multicols}{3}
\xintiloop [1+1]
\edef\Z {\xinttheiiexpr
(\pdfuniformdeviate 1000)^2
*\pdfuniformdeviate 1000\relax }%
$\sqrt{\Z}=\Rsqrt{\Z}$\par
\ifnum\xintiloopindex<51
\repeat
\end{multicols}
\end{document}
Aktualisierung (2017).
Hier ist ein nicht paketierbares erweiterbares Makro, falls erforderlich. Es wird bis zum Original erweitert und I,J
ist quadratfrei . Verwendet nur . Beschränkt auf ganze Zahlen. Funktioniert von klein nach groß, genauso wie die Methode der elementaren Faktorisierung. Die Abbruchkriterien sollten verbessert werden, der Kommentar unten gilt auch hier.N
I**2 times J
J
\numexpr
<2**31
\makeatletter
\newcommand\ExtractRadical[1]{%
\romannumeral0%
\expandafter
\ExtractRadical@two@i\expandafter1\expandafter,\the\numexpr#1.%
}%
\def\ExtractRadical@two@i #1,#2.{%
\ifnum4>#2 \expandafter\ExtractRadical@two@done\fi
\expandafter\ExtractRadical@two@ii\the\numexpr#2/4;#1,#2.%
}%
\edef\ExtractRadical@two@done #1;#2,#3.%
{\space#2,#3}% (not sole #2 for readability)
\def\ExtractRadical@two@ii #1;#2,#3.{%
\ifnum\numexpr#1*4=#3
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\expandafter\ExtractRadical@two@i\the\numexpr2*#2,#1.}%
{\ExtractRadical@i 3;#2,#3.}%
}%
\def\ExtractRadical@i #1;{%
\expandafter\ExtractRadical@ii\the\numexpr#1*#1.#1;%
}%
\def\ExtractRadical@ii #1.#2;#3,#4.{%
\ifnum#1>#4 \expandafter\ExtractRadical@done\fi
\expandafter\ExtractRadical@iii\the\numexpr#4/#1.#1;#4.#2;#3.%
}%
\def\ExtractRadical@iii #1.#2;#3.{%
\ifnum\numexpr#1*#2=#3
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
\ExtractRadical@update
\ExtractRadical@next
#1.#2;#3.%
}%
\def\ExtractRadical@update #1.#2;#3.#4;#5.{%
\expandafter\ExtractRadical@ii
\the\numexpr#2\expandafter.%
\the\numexpr#4\expandafter;%
\the\numexpr#4*#5,#1.%
}%
\def\ExtractRadical@next #1.#2;#3.#4;#5.{%
\expandafter\ExtractRadical@i\the\numexpr2+#4;#5,#3.%
}%
\edef\ExtractRadical@done #1;#2.#3;#4.{\space#4,#2}%
\makeatother
Antwort2
Hier ist eine LuaLaTeX-basierte Lösung. Der Code richtet ein LaTeX-Makro namens ein \rsqrt
, das eine Lua-Funktion namens aufruft rsqrt
. Letztere implementiert den von Ihnen vorgeschlagenen Vereinfachungsalgorithmus – mit den folgenden Verfeinerungen:
Für
n=0
odern=1
gibt der Code einfach etwas zurückn
(ohne Wurzelsymbol); undEs wird darauf geachtet, den
\sqrt{n/i²}
Term wegzulassen, wenn er gleich ist1
, d. h. wennn
eine „Quadratzahl“ (4, 9, 16 usw.) oder ein Produkt kleinerer Quadratzahlen ist. Wenn beispielsweisen=36
,\rsqrt{36}
wird angezeigt ,6
da36 = 6^2 = 2^2*3^2
.
Es wird keine Überprüfung der Eingabe auf Plausibilität durchgeführt, d. h. der Benutzer ist dafür verantwortlich, ein Argument anzugeben, das entweder eine nicht-negative ganze Zahl ist oder als eine nicht-negative ganze Zahl ausgewertet wird. Daher ist es in Ordnung, und \rsqrt
zu schreiben : Das Makro gibt bzw. zurück .\rsqrt{1e6}
\rsqrt{3.6e7}
1000
6000
Beachten Sie, dass das Makro \rsqrt
im Mathematikmodus verwendet werden muss, da es \sqrt
Anweisungen ausgeben kann.
% !TEX TS-program = lualatex
%% Note: Code updated 2019/10/26 to work with LaTeX 2019-10-01
%% Create an external file to contain the Lua code
\begin{filecontents*}[overwrite]{rsqrt.lua}
function rsqrt ( n )
-- n : a non-negative whole number (or something
-- that evaluates to a non-neg. whole number)
if n == 0 or n == 1 then -- Nothing to do
return ( n )
else
i = math.floor ( math.sqrt ( n ) )
while i > 1 do
if ( n % i^2 == 0 ) then -- n is divisible by i^2
k = math.floor ( n / i^2 ) -- 'math.floor' makes k an explicit integer
if k == 1 then -- n is a "square" number (or a product of square numbers)
return ( i )
else
return ( i .. "\\sqrt{" .. k .. "}" )
end
end
i = i-1
end
-- No simplification possible:
return ( "\\sqrt{" .. n .. "}" )
end
end
-- Define a vector (in form of a Lua table) of whole numbers
nvec = {0,1,2,3,4,5,7,12,16,18,27,32}
-- Lua function to print 3-column array:
function PrintArray()
for i=1,#nvec do
u = nvec[i]
tex.sprint ( math.floor(u) ..
"& \\sqrt{" .. math.floor(u) ..
"}&" .. rsqrt(u) .. "\\\\" )
end
end
\end{filecontents*}
\documentclass{article}
%% Load Lua code from external file:
\directlua{dofile("rsqrt.lua")}
%% TeX-side code: "wrapper" macro that invokes the Lua function:
\newcommand\rsqrt[1]{\directlua{tex.sprint(rsqrt(#1))}}
\begin{document}
\[
\renewcommand\arraystretch{1.25}
\begin{array}{@{} rcc @{}}
\verb+n+ & \verb+\sqrt+ & \verb+\rsqrt+ \\ % print header row
\directlua{PrintArray()} % create and print body of 'array'
\end{array}
\]
\end{document}
Antwort3
In expl3
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\rsqrt}{m}
{
\manual_rsqrt:n { #1 }
}
\int_new:N \l_manual_rsqrt_int
\cs_new_protected:Nn \manual_rsqrt:n
{
\int_set:Nn \l_manual_rsqrt_int { \fp_to_decimal:n { trunc(sqrt(#1),0) } }
\bool_until_do:nn
{
\int_compare_p:n { \int_mod:nn { #1 } { \l_manual_rsqrt_int * \l_manual_rsqrt_int } == 0 }
}
{
\int_decr:N \l_manual_rsqrt_int
}
\int_compare:nTF { \l_manual_rsqrt_int == 1 }
{
\sqrt{#1}
}
{
\int_to_arabic:n { \l_manual_rsqrt_int }
\int_compare:nF { #1 == \l_manual_rsqrt_int*\l_manual_rsqrt_int }
{
\sqrt{ \int_to_arabic:n { #1/(\l_manual_rsqrt_int*\l_manual_rsqrt_int) } }
}
}
}
\ExplSyntaxOff
\begin{document}
$\rsqrt{4}$
$\rsqrt{8}$
$\rsqrt{18}$
$\rsqrt{12}$
$\rsqrt{7}$
\end{document}
Wenn Sie mit den Argumenten 0 und 1 und auch mit negativen Argumenten arbeiten möchten, können Sie die Hauptdefinition ändern in
\NewDocumentCommand{\rsqrt}{m}
{
\int_compare:nTF { #1 < 0 }
{
\int_compare:nTF { #1 = -1 } { i } { \manual_rsqrt:n { -#1 } i }
}
{
\int_compare:nTF { #1 < 2 } { #1 } { \manual_rsqrt:n { #1 } }
}
}
Nun die Eingabe
$\rsqrt{0}$ and $\rsqrt{1}$
$\rsqrt{-1}$ and $\rsqrt{-4}$ and $\rsqrt{-32}$
würde ausgeben
Antwort4
Wenn Sie nicht abgeneigt sind, LaTeX zu verlassen, finden Sie hier eine Lösung mit dem pythontex
Paket. Ich habe es sroot
für simple root genannt. Natürlich können Sie es nennen, wie Sie wollen. Diese Version erfordert ein
pdflatex *filename*.tex
,
pythontex filename*.tex
,
pdflatex *filename*.tex
Ausführungssequenz für Ihr Dokument.
\documentclass{article}
\usepackage{pythontex}
\begin{document}
\newcommand{\sroot}[1]{\ensuremath{\py{simpleroot(#1)}}}
\begin{pycode}
from math import *
def simpleroot(n):
if n==0:
return(str(0))
j=int(sqrt(n))
flag_continue=True
while flag_continue:
b=n*1./(j*j)
if b==int(b):
mystring=str(j)+'\\sqrt{'+str(int(b)) +'}'
flag_continue=False
else:
j-=1
if int(b)==1:
mystring=str(j)
if int(b)==n and b>1:
mystring='\\sqrt{'+str(int(b)) +'}'
return(mystring)
\end{pycode}
This is a test.
The $\sqrt{1}$ is \sroot{1}.
The $\sqrt{4}$ is \sroot{4}.
The $\sqrt{7}$ is \sroot{7}.
The $\sqrt{8}$ is \sroot{8}.
The $\sqrt{18}$ is \sroot{18}.
The $\sqrt{23}$ is \sroot{23}.
The $\sqrt{27}$ is \sroot{27}.
The $\sqrt{32}$ is \sroot{32}.
The $\sqrt{64}$ is \sroot{64}.
The $\sqrt{80}$ is \sroot{80}.
The $\sqrt{1000}$ is \sroot{1000}.
The $\sqrt{3000033}$ is \sroot{3000033}.
Goodbye.
\end{document}