Simplificando raízes quadradas

Simplificando raízes quadradas

Quero criar um comando que, para um determinado número inteiro n, digite uma raiz quadrada simplificada de n. Por exemplo, a saída de

\rsqrt{4}
\rsqrt{8}
\rsqrt{18}
\rsqrt{7}

seria igual ao de

2
2\sqrt{2}
3\sqrt{2}
\sqrt{7}

onde \rsqrt{}está o comando em questão.

Eu sei que o algoritmo seria mais ou menos assim

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

onde né o número inteiro fornecido, ié o número anterior \sqrte n/i²é o argumento de \sqrt{...}.

Mas não tenho ideia de como implementar isso no látex?

EDIT: Esclarecido que o número de entrada será sempre um número inteiro.

Responder1

O algoritmo em questão é muito ineficiente: exceto, é claro, se o número inteiro original for um quadrado perfeito.

Esta resposta (em ordem cronológica):

  1. uma abordagem com macros que imita o algoritmo de fatoração mais simples,

  2. uma abordagem expansível usando o algoritmo como no OP.atualizarmuito embaraçosamente, o autor não havia entendido o algoritmo do OP e depois de ter encontrado uma simplificação Icomo I^2dividida N, foi recursivamente sem N<-N/I^2entender que o algoritmo poderia parar por aí. (como uma desculpa esfarrapada, ele implementou primeiro o modo "de baixo para cima", que precisa de recursividade, ao contrário do modo "de cima para baixo" (menos eficiente). A resposta é, portanto, atualizada, desculpas a todos os eleitores iniciais generosos e confiáveis.

    Estou atualizando novamente (desculpe) porque agora li mais xintexpr.stya documentação do e mudei para eficiência de i=sqrt(N)..1para i=-sqrt(N)++(não há --disponível, portanto, um truque com sinal de menos). O primeiro gera de antemão toda a lista de floor(\sqrt{N})números ( sqrtsignifica raiz quadrada truncada \xintiiexpr), o último é um iterador que não gera coisas de antemão. Além disso, a sintaxe anterior só pode gerar 5000valores about ( sqrt(N)..[-1]..1não teria tal limitação, mas ainda assim geraria tudo de antemão).

  3. uma implementação expansível de algoritmo mais rápido (tipo fatoração para ensino médio), como na abordagem 1.

Para ser honesto, 2., 3. e até 1. provavelmente seriam melhor escritos inteiramente usando \numexprcomo pretensão de lidar com números maiores do que 2^31o que é um pouco esticado, leva tempo com um número primo de 10 dígitos para fazer dezenas de milhares de divisões para concluir que era livre de quadrados ... A implementação 2. tem um limite intrínseco porque 2^62a raiz quadrada deve ser um número TeX (devido a alguma construção interna).

Em 2. e 3., levamos um pouco além do razoável as possibilidades de \xintexprsintaxe com sequências recursivas. A notação é um pouco complicada. Além disso, xintexpr.sty 1.2gé necessário porque alterou a sintaxe relevante.

  1. finalmente (2017), também adiciono a abordagem expansível apenas sem pacote numexpr.

Primeira abordagem (mudamos o algoritmo)

Não quer dizer que este seja um problema fácil. Uma pequena pesquisa no Google revela que aparentemente os matemáticos acreditam atualmente que encontrar o radical livre quadrado de um número inteiro pode ser tão difícil quanto a fatoração completa:https://math.stackexchange.com/questions/171568/finding-the-radical-of-an-integerehttps://math.stackexchange.com/questions/14667/square-free-integers-factorization.

Aqui está uma abordagem (usando macros) que imita a forma mais simples de algoritmo de fatoração.

O pacote xintexpré usado apenas para permitir entradas como 1e7ou mesmo expressões. Ele também carrega xinttoolso que é usado na sintaxe.

Além disso, todas as operações são feitas com macros disponíveis em xint. Como no exemplo tratamos quase apenas de números <2^31poderíamos empregar uma variante onde todas as operações seriam feitas usando uniquely \numexpr, naturalmente isso seria bem mais rápido.

O código usa \xintiiDivisionwhich calcula simultaneamente quociente e resto. É por isso que \xintAssigné usado para armazená-los em duas macros \Ae arquivos \B. O código examina if \Bdesaparece para detectar a divisibilidade por a 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}

insira a descrição da imagem aqui


Segunda abordagem (mesmo algoritmo do OP, implementação expansível)

Com o algoritmo original. Aqui definimos \ExtractRadicalqual retorna de forma expansível A,Bcom N=A^2 B. Um invólucro não expansível recicla \Rsqrtda abordagem mais rápida acima para produzir A\sqrt{B}, distinguindo casos de negativo Nou N=0, 1.

Adicionei comentários de código para explicar a implementação. Uma versão anterior era muito fraca (veja o início da resposta) e era adicionalmente necessária, xintexpr 1.2go que não é mais o caso.

\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}

insira a descrição da imagem aqui


Terceira abordagem: novamente o algoritmo mais rápido, mas de forma expansível.

Seria mais razoável codificar isso à la \numexprmas bem. Detalhes no comentário do código. O exemplo agora tem 51 exemplos aleatórios, e o engraçado é que o que faltava (da primeira abordagem) acabou sendo um quadrado aleatório (com a semente aleatória para o gerador de números aleatórios pdftex definido como 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}

insira a descrição da imagem aqui


Atualização (2017).

Aqui está uma macro expansível sem pacote, se necessário. Ele se expande para I,Jonde o original Nestá I**2 times Je Jnão tem quadrados. Usa apenas \numexpr. Limitado a <2**31números inteiros. Funciona de baixo para grande, da mesma forma que o método de fatoração elementar. Os critérios de parada devem ser melhorados, o comentário abaixo também se aplica aqui.

\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

Responder2

Aqui está uma solução baseada em LuaLaTeX. O código configura uma macro LaTeX chamada \rsqrt, que invoca uma função Lua chamada rsqrt. Este último implementa o algoritmo de simplificação que você propôs – com os seguintes refinamentos:

  • Para n=0or n=1, o código simplesmente retorna n(sem símbolo de raiz quadrada); e

  • Tome-se o cuidado de omitir o \sqrt{n/i²}termo se for igual a 1, ou seja, se nfor um "número quadrado" (4, 9, 16, etc) ou um produto de números quadrados menores. Por exemplo, se n=36, \rsqrt{36}mostra 6desde 36 = 6^2 = 2^2*3^2.

Nenhuma verificação de integridade de entrada é executada, ou seja, o usuário é responsável por fornecer um argumento \rsqrtque seja um número inteiro não negativo ou que seja avaliado como um número inteiro não negativo. Assim, não há problema em escrever \rsqrt{1e6}and \rsqrt{3.6e7}: a macro retornará 1000e 6000, respectivamente.

Observe que a macro \rsqrtdeve ser usada no modo matemático, pois pode gerar \sqrtdiretivas.

insira a descrição da imagem aqui

% !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} 

Responder3

Em 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}

insira a descrição da imagem aqui

Se você quiser lidar com os argumentos 0 e 1 e também com argumentos negativos, você pode alterar a definição principal para

\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 } }
   }
 }

Agora a entrada

$\rsqrt{0}$ and $\rsqrt{1}$

$\rsqrt{-1}$ and $\rsqrt{-4}$ and $\rsqrt{-32}$

produziria

insira a descrição da imagem aqui

Responder4

Se você não tem aversão a sair do LaTeX, aqui está uma solução usando o pythontexpacote. Eu chamei srootde root simples. Obviamente, você pode chamá-lo do que quiser. Esta versão requer um

pdflatex *filename*.tex, pythontex filename*.tex, pdflatex *filename*.texsequência de execução do seu documento.

\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}

informação relacionada