Trop vite, trop Fourier: FFT Code Golf

48

Implémentez la transformation de Fourier rapide dans le moins de caractères possible.

Règles:

  • La solution la plus courte gagne
  • On peut supposer que l'entrée est un tableau 1D dont la longueur est une puissance de deux.
  • Vous pouvez utiliser l’algorithme de votre choix, mais la solution doit en réalité être une transformation de Fourier rapide, et pas seulement une transformation de Fourier discrète naïve (c’est-à-dire qu’elle doit avoir un coût de calcul asymptotique de ).O(NlogN)

Modifier:

  • le code doit implémenter la transformée de Fourier rapide vers l'avant standard, dont on peut voir la forme dans l'équation (3) de cet article de Wolfram ,

    entrez la description de l'image ici

  • L'utilisation d'une fonction FFT à partir d'une bibliothèque standard préexistante ou d'un package de statistiques n'est pas autorisée. Le défi consiste ici à implémenter succinctement l’algorithme FFT lui-même.
jakevdp
la source
3
Ceci est sous-spécifié. Au minimum, vous devez définir les facteurs de normalisation et vous devez également savoir que toute ambiguïté sera volontairement mal interprétée. Par exemple, "Implement" est-il satisfait par la réponse " FFT(3 caractères): c'est dans la bibliothèque standard"? Certains cas de test seraient bien aussi.
Peter Taylor
Importe-t-il l’ordre des éléments de sortie, c’est-à-dire que nous devons implémenter le désembrouillage inversé sur bits ou pouvons-nous laisser la sortie dans l’ordre brouillé?
Paul R
Voir les modifications apportées aux règles. La sortie doit être une liste / un tableau avec des valeurs ordonnées en fonction des indices de l'expression DFT standard, référencée ci-dessus.
jakevdp
2
Pouvez-vous publier des exemples d'entrées et de sorties afin que nous puissions tester nos implémentations?
FUZxxl
2
Le titre aurait dû être "Fast and Fourier-s" (Fast and Furious).
Clismique

Réponses:

12

Mathematica, 95 octets

Une autre implémentation de la FFT Cooley – Tukey avec l'aide de @ chyaong .

{n=Length@#}~With~If[n>1,Join[+##,#-#2]&[#0@#[[;;;;2]],#0@#[[2;;;;2]]I^Array[-4#/n&,n/2,0]],#]&

Ungolfed

FFT[x_] := With[{N = Length[x]},
  If[N > 1,
    With[{a = FFT[ x[[1 ;; N ;; 2]] ], 
          b = FFT[ x[[2 ;; N ;; 2]] ] * Table[E^(-2*I*Pi*k/N), {k, 0, N/2 - 1}]},
      Join[a + b, a - b]],
    x]]
milles
la source
1
Je pense #[[;;;;2]]==#[[1;;N;;2]]et [[2;;;;2]]==[[2;;N;;2]].
chyanog
1
101 caractères :With[{L=Length@#},If[L>1,Join[+##,#-#2]&[#0@#[[;;;;2]],#0@#[[2;;;;2]]E^(-2I*Pi(Range[L/2]-1)/L)],#]]&
chyanog
Bien, vous pouvez condenser une autre fonction anonyme à l'intérieur sans entrer en conflit avec la fonction récursive. Également appris que la partie remplit les index manquants. Nous pouvons aller plus loin en utilisant Unicode.
miles
9

J, 37 octets

_2&(0((+,-)]%_1^i.@#%#)&$:/@|:]\)~1<#

Une amélioration après quelques années. Utilise toujours l'algorithme FFT de Cooley-Tukey.

Sauvegardé 4 octets en utilisant e πi = -1, grâce à @ Leaky Nun .

Essayez-le en ligne!

Usage

   f =: _2&(0((+,-)]%_1^i.@#%#)&$:/@|:]\)~1<#
   f 1 1 1 1
4 0 0 0
   f 1 2 3 4
10 _2j2 _2 _2j_2
   f 5.24626 3.90746 3.72335 5.74429 4.7983 8.34171 4.46785 0.760139
36.9894 _6.21186j0.355661 1.85336j_5.74474 7.10778j_1.13334 _0.517839 7.10778j1.13334 1.85336j5.74474 _6.21186j_0.355661

Explication

_2&(0((+,-)]%_1^i.@#%#)&$:/@|:]\)~1<#  Input: array A
                                    #  Length
                                  1<   Greater than one?
_2&(                            )~     Execute this if true, else return A
_2                            ]\         Get non-overlapping sublists of size 2
    0                       |:           Move axis 0 to the end, equivalent to transpose
                          /@             Reduce [even-indexed, odd-indexed]
                       &$:               Call recursively on each 
                   #                     Get the length of the odd list
                i.@                      Range from 0 to that length exclusive
                    %#                   Divide each by the odd length
             _1^                         Compute (-1)^x for each x
           ]                             Get the odd list
            %                            Divide each in that by the previous
       +                                 Add the even values and modified odd values
         -                               Subtract the even values and modified odd values
        ,                                Join the two lists and return
milles
la source
1
Voir aussi, ceci: blog.ndpar.com/2014/10/11/dft-j
FUZxxl
9

Python, 166 151 150 caractères

Ceci utilise l'algorithme FFT de radix-2 Cooley-Tukey

from math import*
def F(x):N=len(x);t=N<2or(F(x[::2]),F(x[1::2]));return N<2and x or[
a+s*b/e**(2j*pi*n/N)for s in[1,-1]for(n,a,b)in zip(range(N),*t)]

Tester le résultat

>>> import numpy as np
>>> x = np.random.random(512)
>>> np.allclose(F(x), np.fft.fft(x))
True
jakevdp
la source
1
2 choses: il est généralement préférable d'utiliser from x import*, et sum(([x for x in y] for y in z),[])est plus long que [x for y in z for x in y].
Boothby
1
Merci - cela sauve 15 caractères! 11 de plus et c'est un tweet.
jakevdp
Oh, c'est certainement possible. Souvent, lorsque vous trouvez une amélioration, une ancienne devient une pierre d'achoppement.
Boothby
5

Python 3: 140 134 113 caractères

Version courte - courte et douce, s'inscrit dans un tweet (avec des miles ):

from math import*
def f(v):
 n=len(v)
 if n<2:return v
 a,b=f(v[::2])*2,f(v[1::2])*2;return[a[i]+b[i]/1j**(i*4/n)for i in range(n)]

(En Python 2, la /division est tronquée lorsque les deux côtés sont des entiers. Nous remplaçons donc (i*4/n)par (i*4.0/n), ce qui réduit la longueur à 115 caractères.)

Version longue - plus de clarté dans les éléments internes du classique FFT Cooley-Tukey:

import cmath
def transform_radix2(vector):
    n = len(vector)
    if n <= 1:  # Base case
        return vector
    elif n % 2 != 0:
        raise ValueError("Length is not a power of 2")
    else:
        k = n // 2
        even = transform_radix2(vector[0 : : 2])
        odd  = transform_radix2(vector[1 : : 2])
        return [even[i % k] + odd[i % k] * cmath.exp(i * -2j * cmath.pi / n) for i in range(n)]
Nayuki
la source
1
Raccourci à 113 octets avece^(-2j * pi * i / n) = (-1)^(2 * i / n) = (1j)^(4 * i / n)
miles
@miles Observation très impressionnante, merci! Après avoir implémenté de manière répétée les DFT pendant plus de 10 ans, je suis devenu obsédé par sin / cos / exp et j'ai oublié que de simples puissances de i peuvent être utilisées. J'ai édité ma réponse pour incorporer la nouvelle idée et vous créditer.
Nayuki
5

R: 142 133 99 95 octets

Merci à @ Giuseppe de m'avoir aidé à réduire de 32 à 36 octets!

f=function(x,n=sum(x|1),y=1:(n/2)*2)`if`(n>1,f(x[-y])+c(b<-f(x[y]),-b)*exp(-2i*(y/2-1)*pi/n),x)

Une astuce supplémentaire consiste à utiliser les arguments par défaut de la fonction principale pour instancier certaines variables.
L'utilisation est toujours la même:

x = c(1,1,1,1)
f(x)
[1] 4+0i 0+0i 0+0i 0+0i

Version 4 ans à 133 octets:

f=function(x){n=length(x);if(n>1){a=Recall(x[seq(1,n,2)]);b=Recall(x[seq(2,n,2)]);t=exp(-2i*(1:(n/2)-1)*pi/n);c(a+b*t,a-b*t)}else{x}}

Avec indentations:

f=function(x){
    n=length(x)
    if(n>1){
        a=Recall(x[seq(1,n,2)])
        b=Recall(x[seq(2,n,2)])
        t=exp(-2i*(1:(n/2)-1)*pi/n)
        c(a+b*t,a-b*t)
        }else{x}
    }

Il utilise également l'algorithme de Cooley-Tukey. Les seules astuces ici sont l'utilisation de la fonction Recallqui permet la récursivité et l'utilisation de la vectorisation R qui raccourcit considérablement le calcul réel.

Usage:

x = c(1,1,1,1)
f(x)
[1] 4+0i 0+0i 0+0i 0+0i
planificateur
la source
1
Quatre ans plus tard, nous avons réduit le nombre d' octets à 101 . Vous n'êtes pas sûr à 100% de la raison pour laquelle vous avez déjà utilisé Recallcette fonction, mais bon, c'est facile de jouer au golf avec le recul! :) +1, très sympa.
Giuseppe
Oui Recallest maintenant inutile, en effet. J'ai remarqué cela il y a quelques mois mais j'étais trop paresseux pour le changer :) Je vais le modifier.
Plannapus
Très agréable! J'ai pressé encore 4 octets! , mettant cela à égalité avec Mathematica.
Giuseppe
Merci! Je pensais yy aller mais je n’ai pas remarqué que cela pourrait également être utile exp(...).
plannapus
4

Python, 134

Ceci emprunte beaucoup à la solution de jakevdp, je l'ai donc définie sur un wiki de communauté.

from math import*
F=lambda x:x*(len(x)<2)or[a+s*b/e**(2j*pi*n/len(x))for s in(1,-1)for n,(a,b)in
enumerate(zip(F(x[::2]),F(x[1::2])))]

Changements:

-12 caractères: tuer t.

def F(x):N=len(x);t=N<2or(F(x[::2]),F(x[1::2]));return ... in zip(range(N),*t)]
def F(x):N=len(x);return ... in zip(range(N),F(x[::2]),F(x[1::2]))]

-1 caractère: astuce de l'exposant, x*y**-z == x/y**z (cela pourrait aider d'autres)

...[a+s*b*e**(-2j*pi*n/N)...
...[a+s*b/e**(2j*pi*n/N)...

-2 caractères: remplacer andpar*

...return N<2and x or[
...return x*(N<2)or[

+1 personnage: lambdaize, tuerN

def F(x):N=len(x);return x*(N<2)or[a+s*b/e**(2j*pi*n/N) ... zip(range(N) ...
F=lambda x:x*(len(x)<2)or[a+s*b/e**(2j*pi*n/len(x)) ... zip(range(len(x)) ...

-2 caractères: utiliser enumerateau lieu dezip(range(len(

...for(n,a,b)in zip(range(len(x)),F(x[::2]),F(x[1::2]))]
...for n,(a,b)in enumerate(zip(F(x[::2]),F(x[1::2])))]
boothby
la source
Je pense que ce n’est plus une transformation de Fourier rapide, cependant ... en "tuant", vous avez ajouté des calculs inutiles qui le déplacent de O [N log (N)] à O [N ^ 2]
jakevdp
Il semble que je ne puisse pas voter ma propre publication. Vous avez raison, j'ai échangé l'ordre des boucles et tué la performance. Je vais laisser cela pour le moment, au cas où je trouverais un moyen de le réparer.
Boothby
101 octets avecf=lambda x:x*(len(x)<2)or[u+v/1j**(4*i/len(x))for i,(u,v)in enumerate(zip(f(x[::2])*2,f(x[1::2])*2))]
miles
Vous pouvez remplacer for s in(1,-1)foravec for s in 1,-1forou même, si l' ordre n'a pas d' importance, for s in-1,1for.
Jonathan Frech
4

C, 259

typedef double complex cplx;
void fft(cplx buf[],cplx out[],int n,int step){
if(step < n){
fft(out, buf,n, step * 2);
fft(out+step,buf+step,n,step*2);
for(int i=0;i<n;i+=2*step){
cplx t=cexp(-I*M_PI*i/n)*out[i+step];
buf[i/2]=out[i]+t;
buf[(i+n)/2]=out[i]-t;
}}}

Le problème est que de telles implémentations sont inutiles et qu'un algorithme simple est BEAUCOUP plus rapide.

Sanaris
la source
2
Vous pouvez supprimer un peu plus d' espaces pour obtenir un bas amout de caractères, par exemple step < npeut être changé en step<net step * 2peut être changé en step*2.
ProgramFOX
2
toutes les variables, fonctions et typedefs doivent avoir des noms d'une lettre pour économiser beaucoup de caractères
2
Vous avez eu quelqu'un suggérer un tas d'améliorations pour cela. Jetez-y un coup d'œil ici: codegolf.stackexchange.com/review/suggested-edits/17119
Justin
1
Vous pouvez supprimer toutes les nouvelles lignes, les nouvelles lignes sont inutiles en C
TuxCrafting
@ TùxCräftîñg Toutes les nouvelles lignes ne sont pas inutiles. Ils sont nécessaires pour les directives telles que #include, #define, #if, etc.
Nayuki
3

Matlab, 128 118 107 102 101 94 93 octets

EDIT6: merci @algmyr pour un autre octet!

function Y=f(Y);
n=numel(Y);
k=2:2:n;
if k;
   c=f(Y(k-1));
   d=f(Y(k)).*i.^(2*(2-k)/n);
   Y=[c+d;c-d];
end

EDIT5: Toujours plus court :) grâce à @sanchises

function Y=f(Y)
n=numel(Y);
k=2:2:n;
if k;
   c=f(Y(k-1));
   d=f(Y(k)).*(-1).^((2-k)/n);
   Y=[c+d;c-d];
end

EDIT4: Yay, -1 caractère de plus (aurait également pu se passer de k):

function Y=f(Y)
n=numel(Y);
if n>1;
   k=2:2:n;
   c=f(Y(k-1));
   d=f(Y(k)).*(-1).^((k/2-1)*2/n)';
   Y=[c+d;c-d];
end

EDIT2 / 3: Merci pour les @sanchises pour d'autres améliorations!

function Y=f(Y)
n=numel(Y);  
if n>1;
   c=f(Y(1:2:n));
   d=f(Y(2:2:n)).*(-1).^(-(0:n/2-1)*2/n).';
   Y=[c+d;c-d]; 
end

EDIT: Pourrait apporter quelques améliorations, et a remarqué que la constante de mise à l'échelle n'est pas requise.

Ceci est la version développée, le nombre de caractères est valide si vous supprimez les nouvelles lignes / espaces. (Fonctionne uniquement pour les vecteurs de colonne.)

function y=f(Y)
n=numel(Y);  
y=Y;
if n>1;
   c=f(Y(1:2:n));
   d=f(Y(2:2:n));
   n=n/2;
   d=d.*exp(-pi*i*(0:n-1)/n).';
   y=[c+d;c-d]; 
end
flawr
la source
Astuce: vous pouvez combiner les deux d=lignes en une seule: m=n/2;d=f(Y(2:2:n)).*exp(-pi*i*(0:m-1)/m).';. En outre, envisager de changer y=f(Y)pour Y=f(Y)et supprimer la ligne 3 (et la promesse que vous ne serez jamais le faire en dehors du code de golf)
Sanchises
Oh merci! At function Y = f(Y)-il des inconvénients autres que l’illisibilité?
Flawr
Eh bien, MATLAB ne se plaindra jamais d’une valeur de retour, même si Y n’est jamais modifié. Cependant, il est légèrement plus rapide, je suppose donc que ce n'est pas si grave après tout (à savoir une fonction qui ne change presque jamais la variable d'entrée)
Sanchises
Maintenant, pour économiser plus: m=n/2pourrait être enlevé, et mremplacé à la place par n/2et n*2respectivement. Et puis, je crois fermement, le programme est aussi court que ce que pourrait être MATLAB.
Sanchises
1
Et puis, je crois fermement, le programme est aussi court que ce que pourrait être MATLAB. - Sanchises 8 mars 15 à 21:05
Derniers
2

Jelly, 31 30 28 26 octets , non en compétition

LḶ÷$N-*×,N$+ḷF
s2Z߀ç/µ¹Ṗ?

Jelly a été créée après ce défi, elle est donc non compétitive.

Ceci utilise l'algorithme récursif de Cooley-Tukey radix-2. Pour une version sans jeu, voir ma réponse dans Mathematica.

Essayez-le en ligne ou vérifiez plusieurs scénarios de test .

Explication

LḶ÷$N-*×,N$+ḷF  Helper link. Input: lists A and B
L               Get the length of A
   $            Operate on that length
 Ḷ                Make a range [0, 1, ..., length-1]
  ÷               Divide each by length
    N           Negate each
     -          The constant -1
      *         Compute -1^(x) for each x in that range
       ×        Multiply elementwise between that range and B, call it B'  
          $     Operate on that B'
         N        Negate each
        ,         Make a list [B', -B']
            ḷ   Get A
           +    Add vectorized, [B', -B'] + A = [A+B', A-B']
             F  Flatten that and return

s2Z߀ç/µ¹Ṗ?  Main link. Input: list X
         Ṗ   Curtail - Make a copy of X with the last value removed
          ?  If that list is truthy (empty lists are falsey)
       µ       Parse to the left as a monad
s2             Split X into sublists of length 2
  Z            Transpose them to get [even-index, odd-index]
   ߀          Call the main link recursively on each sublist
     ç/        Call the helper link as a dyad on the sublists and return
             Else
        ¹      Identity function on X and return
milles
la source
2

C (gcc) , 188 186 184 183 octets

#define d(a,b,c)f(a,b,c,1,0)
f(a,b,c,n,k)_Complex*a,*b;{_Complex z[c];*b=*a;if(n<c)for(f(a,z,c,n*2),f(a+n,z+n,c,n*2);k<c;k+=n*2)b[k+c>>1]=z[k]*2-(b[k/2]=z[k]+z[k+n]/cpow(1i,2.*k/c));}

Essayez-le en ligne!

Légèrement golfé moins

#define d(a,b,c)f(a,b,c,1,0)
f(a,b,c,n,k)_Complex*a,*b;{
  _Complex z[c];
  *b=*a;
  if(n<c)
    for(f(a,z,c,n*2),f(a+n,z+n,c,n*2);k<c;k+=n*2)
      b[k+c>>1]=z[k]*2-(b[k/2]=z[k]+z[k+n]/cpow(1i,2.*k/c));
}
plafondcat
la source
1

Pari / GP, 76 caractères

X(v)=my(t=-2*Pi*I/#v,s);vector(#v,k,s=t*(k-1);sum(n=0,#v-1,v[n+1]*exp(s*n)))

Usage

X([1,1,1,1])
%2 = [4.000000000000000000000000000, 0.E-27 + 0.E-28*I, 0.E-28 + 0.E-27*I, 0.E-27 + 0.E-28*I]
P̲̳x͓L̳
la source
3
N'est-ce pas la DFT naïve? (ie theta (N ^ 2))
miles
1

Octave , 109 103 101 100 octets

f(f=@(f)@(x,n=rows(x)){@(d=f(f)(x(k=2:2:n)).*i.^((k*2-4)/n)')[d+(c=f(f)(x(k-1)));c-d],x}{1+(n<2)}())

Essayez-le en ligne!

Ooooo mes yeux saignent de ce lambda maudit récursif . De grandes parties de ceci ont été retirées de la réponse de @ flawr.

f(                                          % lambda function
  f=@(f)                                    % defined in its own argument list, 
                                            % accepts itself as parameter (for recursion)
    @(x,n=rows(x)){                         % calls another lambda,
                                            % 2nd parameter is just to define a variable
      @(d=f(f)(x(k=2:2:n)).*i.^((k*2-4)/n)')% 1/4 of FFT (argument just defines a variable)
        [d+(c=f(f)(x(k-1)));                % 2/4 of FFT
         c-d                                % 4/4 of FFT
        ],                                  % This is in a @()[] to inhibit evaluation
                                            % unless actually called
      x                                     % FFT of length 1
    }{1+(n<2)}                              % if len(x)==1, return x
                                            % else return [d+c;c-d]
  ()                                        % this is probably important too
)
plafondcat
la source
Je ne comprends pas ce que tu as fait mais j'aime beaucoup.
mardi
1

APL (NARS), 58 caractères, 116 octets

{1≥k←≢⍵:⍵⋄(∇⍵[y∼⍨⍳k])(+,-)(∇⍵[y←2×⍳t])×0J1*t÷⍨2-2×⍳t←⌊k÷2}

tester

  f←{1≥k←≢⍵:⍵⋄(∇⍵[y∼⍨⍳k])(+,-)(∇⍵[y←2×⍳t])×0J1*t÷⍨2-2×⍳t←⌊k÷2}
  f 1 1 1 1
4J0 0J0 0J0 0J0 
  f 1 2 3 4
10J0 ¯2J2 ¯2J0 ¯2J¯2 
  f 1J1 2 ¯2J1  9
10J2 3J7 ¯12J2 3J¯7 
  f 5.24626,3.90746,3.72335,5.74429,4.7983,8.34171,4.46785,0.760139
36.989359J0 ¯6.211855215J0.3556612739 1.85336J¯5.744741 7.107775215J¯1.133338726 ¯0.517839J0 
  7.107775215J1.133338726 1.85336J5.744741 ¯6.211855215J¯0.3556612739 
RosLuP
la source
0

Axiome, 259 , 193 , 181 , 179 octets

L(g,n,f)==>[g for i in 1..n|f]
h(a)==(n:=#a;n=1=>a;c:=h(L(a.i,n,odd? i));d:=h(L(a.i,n,even? i));n:=n/2;t:=1>0;v:=L(d.i*%i^(-2*(i-1)/n),n,t);append(L(c.i+v.i,n,t),L(c.i-v.i,n,t)))

Même si h (a) pourrait passer tout le test et serait acceptable, comme entrée pour ce «concours», il faut appeler h () ou hlp () à travers fft () ci-dessous, pour vérifier les arguments . Je ne sais pas si ce logiciel peut fonctionner, car j’ai seulement vu ce que les autres ont écrit et j’ai cherché comment il pourrait fonctionner dans Axiom pour obtenir un résultat correct. Ci-dessous du code non-golfé avec quelques commentaires:

-- L(g,n,f)==>[g for i in 1..n|f]
-- this macro L, build one List from other list, where in g, there is the generic element of index i
-- (as a.i, or a.i*b.i or a.i*4), n build 1..n that is the range of i, f is the condition 
-- for insert the element in the list result.

hlp(a)==
    n:=#a;n=1=>a
    -- L(a.i,n,odd? i)  it means build a list getting "even indices i of a.i as starting from index 0" [so even is odd and odd is even]
    -- L(a.i,n,even? i) it means build a list getting "odd  indices i of a.i as starting from index 0"
    c:=hlp(L(a.i,n,odd? i));d:=hlp(L(a.i,n,even? i))
    n:=n/2;t:=1>0
    v:=L(d.i*%i^(-2*(i-1)/n),n,t)
    append(L(c.i+v.i,n,t),L(c.i-v.i,n,t))

-- Return Fast Fourier transform of list a, in the case #a=2^n
fft(a)==(n:=#a;n=0 or gcd(n,2^30)~=n=>[];hlp(a))

(5) -> h([1,1,1,1])
   (5)  [4,0,0,0]
                                    Type: List Expression Complex Integer
(6) -> h([1,2,3,4])
   (6)  [10,- 2 + 2%i,- 2,- 2 - 2%i]
                                    Type: List Expression Complex Integer
(7) -> h([5.24626,3.90746,3.72335,5.74429,4.7983,8.34171,4.46785,0.760139])
   (7)
   [36.989359, - 6.2118552150 341603904 + 0.3556612739 187363298 %i,
    1.85336 - 5.744741 %i, 7.1077752150 341603904 - 1.1333387260 812636702 %i,
    - 0.517839, 7.1077752150 341603904 + 1.1333387260 812636702 %i,
    1.85336 + 5.744741 %i,
    - 6.2118552150 341603904 - 0.3556612739 187363298 %i]
                                      Type: List Expression Complex Float
(8) -> h([%i+1,2,%i-2,9])
   (8)  [10 + 2%i,3 + 7%i,- 12 + 2%i,3 - 7%i]
                                    Type: List Expression Complex Integer

dans quelques-uns que j'avais vu h () ou fft () renverrait la solution exacte, mais si la simplification n'est pas bonne comme dans:

(13) -> h([1,2,3,4,5,6,7,8])
   (13)
                    +--+                                   +--+
        (- 4 + 4%i)\|%i  - 4 + 4%i             (- 4 - 4%i)\|%i  - 4 + 4%i
   [36, --------------------------, - 4 + 4%i, --------------------------, - 4,
                    +--+                                   +--+
                   \|%i                                   \|%i
            +--+                                   +--+
    (- 4 + 4%i)\|%i  + 4 - 4%i             (- 4 - 4%i)\|%i  + 4 - 4%i
    --------------------------, - 4 - 4%i, --------------------------]
                +--+                                   +--+
               \|%i                                   \|%i
                                    Type: List Expression Complex Integer

qu’il suffit d’en changer le type d’un seul élément de la liste, comme dans l’écriture ci-dessous 8. (Float) pour trouver la solution approximative:

(14) -> h([1,2,3,4,5,6,7,8.])
   (14)
   [36.0, - 4.0000000000 000000001 + 9.6568542494 923801953 %i, - 4.0 + 4.0 %i,
    - 4.0 + 1.6568542494 92380195 %i, - 4.0, - 4.0 - 1.6568542494 92380195 %i,
    - 4.0 - 4.0 %i, - 4.0 - 9.6568542494 923801953 %i]
                                      Type: List Expression Complex Float

Je l'ai écrit, vu toutes les autres réponses car dans le lien, la page était trop difficile, donc je ne sais pas si ce code peut être correct. Je ne suis pas un expert, donc tout cela peut (il est probable) se tromper.

RosLuP
la source