Implementare un numero in virgola mobile binario IEEE 754 a 64 bit mediante la manipolazione di numeri interi


12

(Per il momento ho taggato la domanda "C", ma se sei a conoscenza di un'altra lingua che supporta i sindacati, puoi anche usarla.)

Il tuo compito è costruire i quattro operatori matematici standard + - * /per la seguente struttura:

union intfloat{
    double f;
    uint8_t h[8];
    uint16_t i[4];
    uint32_t j[2]; 
    uint64_t k;
    intfloat(double g){f = g;}
    intfloat(){k = 0;}
}

in modo tale che le operazioni stesse manipolino o accedano sempre alla parte intera (quindi nessun confronto con il doppio in qualsiasi momento durante l'operazione) e il risultato è esattamente lo stesso (o funzionalmente equivalente, nel caso di risultati non numerici come NaN) come se l'operazione matematica corrispondente fosse stata applicata direttamente al doublecontrario.

Puoi scegliere quale parte intera manipolare, magari usando anche parti diverse tra operatori diversi. (Puoi anche scegliere di rimuovere il "unsigned" da uno qualsiasi dei campi nell'unione, anche se non sono sicuro che tu voglia farlo.)

Il tuo punteggio è la somma della lunghezza del codice in caratteri per ciascuno dei quattro operatori. Il punteggio più basso vince.

Per quelli di noi che non hanno familiarità con la specifica IEEE 754, ecco un articolo al riguardo su Wikipedia.


modifiche:

03-06 08:47 Aggiunti costruttori alla struttura intfloat. Puoi usarli per i test, piuttosto che impostare manualmente il doppio / ecc.


1
Yikes! Dimmi che hai una soluzione.
dmckee --- ex gattino moderatore

4
Hmmm ... forse sarebbe meglio definire intstructin termini di uint8_8, uint16_te così via, come le dimensioni assolute di short, inte così via non sono definite dallo standard (ogni tipo ha una dimensione minima e c'è un ordinamento rigoroso nella dimensione, ma questo è tutto).
dmckee --- ex gattino moderatore

1
Immagino che questa sia una grande (e stimolante) pratica anche se non golfata
John Dvorak

3
Questa domanda potrebbe utilizzare la documentazione di come viene gestito l'arrotondamento e una buona suite di test.
Peter Taylor

4
Sono sicuro che è nelle specifiche, ma le specifiche reali costeranno alcune centinaia di dollari. Probabilmente ci sono descrizioni che sono disponibili gratuitamente, ma IMO dovrebbe essere l'onere della domanda per includere quel tipo di dettagli (o almeno un link a un sito che probabilmente sarà ancora in giro tra un paio d'anni) entro la domanda piuttosto che sui rispondenti per cercare se stessi i materiali necessari per sapere cosa vuole effettivamente la domanda.
Peter Taylor,

Risposte:


11

C ++, ~ 1500 caratteri

Espande i float in una rappresentazione a virgola fissa di 8000 cifre binarie, esegue le operazioni su di esso, quindi converte indietro.

// an "expanded" float.                                                                                                         
// n is nan, i is infinity, z is zero, s is sign.                                                                               
// nan overrides inf, inf overrides zero, zero overrides digits.                                                                
// sign is valid unless nan.                                                                                                    
// We store the number in fixed-point, little-endian.  Binary point is                                                          
// at N/2.  So 1.0 is N/2 zeros, one, N/2-1 zeros.                                                                              
#define N 8000
struct E {
  int n;
  int i;
  int z;
  long s;
  long d[N];
};
#define V if(r.n|r.i|r.z)return r
// Converts a regular floating-point number to an expanded one.                                                                 
E R(F x){
  long i,e=x.k<<1>>53,m=x.k<<12>>12;
  E r={e==2047&&m!=0,e==2047,e+m==0,x.k>>63};
  if(e)m+=1L<<52;else e++;
  for(i=0;i<53;i++)r.d[2925+e+i]=m>>i&1;
  return r;
}
E A(E x,E y){
  int i,c,v;
  if(x.s>y.s)return A(y,x);
  E r={x.n|y.n|x.i&y.i&(x.s^y.s),x.i|y.i,x.z&y.z,x.i&x.s|y.i&y.s|~x.i&~y.i&x.s&y.s};V;
  if(x.s^y.s){
    c=0;
    r.z=1;
    for(i=0;i<N;i++){
      v=x.d[i]-y.d[i]-c;
      r.d[i]=v&1;c=v<0;
      r.z&=~v&1;
    }
    if(c){x.s=1;y.s=0;r=A(y,x);r.s=1;}
  }else{
    c=0;
    for(i=0;i<N;i++){
      v=x.d[i]+y.d[i]+c;
      r.d[i]=v&1;c=v>1;
    }
  }
  return r;
}
E M(E x, E y){
  int i;
  E r={x.n|y.n|x.i&y.z|x.z&y.i,x.i|y.i,x.z|y.z,x.s^y.s};V;
  E s={0,0,1};
  for(i=0;i<6000;i++)y.d[i]=y.d[i+2000];
  for(i=0;i<4000;i++){
    if(x.d[i+2000])s=A(s,y);
    y=A(y,y);
  }
  s.s^=x.s;
  return s;
}
// 1/d using Newton-Raphson:                                                                                                    
// x <- x * (2 - d*x)                                                                                                           
E I(E d){
  int i;
  E r={d.n,d.z,d.i,d.s};V;
  E t={};t.d[4001]=1;
  for(i=N-1;i>0;i--)if(d.d[i])break;
  E x={0,0,0,d.s};x.d[N-i]=1;
  d.s^=1;
  for(i=0;i<10;i++)x=M(x,A(t,M(d,x)));
  return x;
}
// Convert expanded number back to regular floating point.                                                                      
F C(E x){
  long i,j,e,m=0;
  for(i=N-1;i>=0;i--)if(x.d[i])break;
  for(j=0;j<N;j++)if(x.d[j])break;
  if(i>0&x.d[i-53]&(j<i-53|x.d[i-52])){E y={0,0,0,x.s};y.d[i-53]=1;return C(A(x,y));}
  if(i<2978){e=0;for(j=0;j<52;j++)m+=x.d[j+2926]<<j;}
  else if(i<5024){e=i-2977;for(j=0;j<52;j++)m+=x.d[i+j-52]<<j;}
  else x.i=1;
  if(x.z)e=m=0;
  if(x.i){e=2047;m=0;}
  if(x.n)e=m=2047;
  F y;y.k=x.s<<63|e<<52|m;return y;
}
// expand, do op, unexpand                                                                                                      
F A(F x,F y){return C(A(R(x),R(y)));}
F S(F x,F y){y.k^=1L<<63;return A(x,y);}
F M(F x,F y){return C(M(R(x),R(y)));}
F D(F x,F y){return C(M(R(x),I(R(y))));}

Sono troppo pigro per rimuovere tutti gli spazi e le nuove righe per ottenere un conteggio esatto del golf, ma sono circa 1500 caratteri.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.