
Я хочу создать команду, которая для заданного целого числа n
типа устанавливает упрощенный квадратный корень из n
. Например, вывод
\rsqrt{4}
\rsqrt{8}
\rsqrt{18}
\rsqrt{7}
будет таким же, как и у
2
2\sqrt{2}
3\sqrt{2}
\sqrt{7}
где \rsqrt{}
находится команда, о которой идет речь.
Я знаю, что алгоритм будет выглядеть примерно так
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
где n
— заданное целое число, i
— число перед ним \sqrt
, а n/i²
— аргумент \sqrt{...}
.
Но я понятия не имею, как это реализовать в латексе?
EDIT: Уточнено, что вводимое число всегда будет целым числом.
решение1
Алгоритм в вопросе очень неэффективен: за исключением, конечно, случая, когда исходное целое число является полным квадратом.
Этот ответ (в хронологическом порядке):
подход с макросами, который имитирует простейший алгоритм факторизации,
расширяемый подход с использованием алгоритма, как в OP.обновлятьочень стыдно, что автор не понял алгоритм OP и после того, как нашел упрощение,
I
такое какI^2
dividedN
, он пошел по нему рекурсивно,N<-N/I^2
не понимая, что алгоритм может остановиться на этом. (в качестве слабого оправдания он сначала реализовал способ "снизу вверх", который требует рекурсии, в отличие от способа "сверху вниз" (менее эффективного)). Таким образом, ответ обновлен, извинения всем великодушным доверчивым ранним голосующим "за".Я снова обновляю (извините), потому что теперь я прочитал больше
xintexpr.sty
документации, и я переключился для эффективности сi=sqrt(N)..1
наi=-sqrt(N)++
(доступного нет--
, отсюда трюк со знаком минус). Первый генерирует заранее весь списокfloor(\sqrt{N})
чисел (sqrt
означает усеченный квадратный корень в\xintiiexpr
), последний является итератором, который ничего не генерирует заранее. Более того, первый синтаксис может генерировать только около5000
значений (sqrt(N)..[-1]..1
не будет иметь такого ограничения, но все равно сгенерирует все заранее).расширяемая реализация более быстрого алгоритма (типа школьной факторизации), как в подходе 1.
Честно говоря, 2., 3. и даже 1., вероятно, было бы лучше написать полностью, используя \numexpr
их притворство об обработке чисел, больших, чем 2^31
, поскольку это немного натянуто, требуется время для простого числа из 10 цифр, чтобы выполнить десятки тысяч делений, чтобы сделать вывод о том, что оно бесквадратное... Реализация 2. имеет внутреннее ограничение, поскольку 2^62
квадратный корень должен быть числом TeX (из-за некоторой внутренней конструкции).
В 2. и 3. мы немного выходим за рамки разумного диапазона возможностей \xintexpr
синтаксиса с рекурсивными последовательностями. Нотация немного громоздкая. Кроме того, xintexpr.sty 1.2g
она нужна, потому что изменила соответствующий синтаксис.
- наконец (2017) я также добавляю расширяемый подход без пакета numexpr.
Первый подход (меняем алгоритм)
Не сказать, что это простая задача. Немного поиска в Google показывает, что, по-видимому, математики в настоящее время считают, что нахождение квадратного свободного радикала целого числа может быть таким же сложным, как полная факторизация:https://math.stackexchange.com/questions/171568/поиск-радикала-целого-числаиhttps://math.stackexchange.com/questions/14667/square-free-integers-factorization.
Вот подход (с использованием макросов), который имитирует простейшую форму алгоритма факторизации.
Пакет xintexpr
используется только для того, чтобы разрешить ввод, такой как 1e7
или даже выражения. Он также загружает xinttools
, что используется в синтаксисе.
Кроме того, все операции выполняются с помощью макросов, доступных из xint
. Поскольку в примере мы имеем дело практически только с числами, <2^31
мы могли бы использовать вариант, где все операции выполнялись бы с использованием uniquely \numexpr
, естественно, это было бы намного быстрее.
Код использует \xintiiDivision
, который одновременно вычисляет частное и остаток. Вот почему \xintAssign
используется для сохранения их в двух макросах \A
и \B
. Код проверяет, \B
исчезает ли , чтобы обнаружить делимость на 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}
Второй подход (такой же алгоритм, как в OP, расширяемая реализация)
С исходным алгоритмом. Здесь мы определяем, \ExtractRadical
какой расширяемый возвращает A,B
с N=A^2 B
. Нерасширяемая оболочка повторяет цикл \Rsqrt
более быстрого подхода выше для получения A\sqrt{B}
, различая случаи отрицательного N
или N=0, 1
.
Я добавил комментарии к коду, чтобы объяснить реализацию. Более ранняя версия была очень хромой (см. начало ответа) и дополнительно требовала, xintexpr 1.2g
что больше не актуально.
\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}
Третий подход: снова более быстрый алгоритм, но с возможностью расширения.
Было бы разумнее закодировать это а-ля \numexpr
но хорошо. Подробности в комментарии к коду. В примере теперь 51 случайный пример, и забавно, что недостающий (из первого подхода) оказался случайным квадратом (со случайным начальным значением для генератора случайных чисел pdftex, установленным на 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}
Обновление (2017).
Вот макрос, расширяемый без пакета, если нужно. Он расширяется до того места, где находится I,J
оригинал, и не содержит квадратов. Использует только . Ограничено целыми числами. Работает от меньшего к большему, как и метод элементарной факторизации. Критерии остановки следует улучшить, комментарий ниже применим и здесь.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
решение2
Вот решение на основе LuaLaTeX. Код устанавливает макрос LaTeX с именем \rsqrt
, который вызывает функцию Lua с именем rsqrt
. Последняя реализует предложенный вами алгоритм упрощения — со следующими уточнениями:
Для
n=0
илиn=1
код просто возвращаетn
(без символа квадратного корня); иСледует проявлять осторожность, чтобы опустить
\sqrt{n/i²}
член, если он равен1
, т. е. еслиn
это «квадратное число» (4, 9, 16 и т. д.) или произведение меньших квадратных чисел. Например, еслиn=36
,\rsqrt{36}
показывает6
, что36 = 6^2 = 2^2*3^2
.
Проверка корректности ввода не выполняется, т. е. пользователь несет ответственность за предоставление аргумента, \rsqrt
который является либо неотрицательным целым числом, либо оценивается как неотрицательное целое число. Таким образом, можно писать \rsqrt{1e6}
и \rsqrt{3.6e7}
: макрос вернет 1000
и 6000
, соответственно.
Обратите внимание, что макрос \rsqrt
необходимо использовать в математическом режиме, поскольку он может выводить \sqrt
директивы.
% !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}
решение3
В 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}
Если вы хотите иметь дело с аргументами 0 и 1, а также с отрицательными аргументами, вы можете изменить основное определение на
\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 } }
}
}
Теперь ввод
$\rsqrt{0}$ and $\rsqrt{1}$
$\rsqrt{-1}$ and $\rsqrt{-4}$ and $\rsqrt{-32}$
выведет
решение4
Если вы не против выйти за рамки LaTeX, вот решение с использованием пакета pythontex
. Я назвал его sroot
для простого корня. Очевидно, вы можете назвать его как угодно. Эта версия требует
pdflatex *filename*.tex
,
pythontex filename*.tex
,
pdflatex *filename*.tex
последовательность выполнения для вашего документа.
\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}