C'era molto tempo fa, mi imbatto in questo pulito e facile da implementare l'algoritmo galleggiante/punto fisso Divison utilizzato in FPU militari di quel periodo di tempo:
ingresso deve essere unsigned e spostato in modo x < y
ed entrambi sono nella gamma < 0.5 ; 1 >
non dimenticate di conservare la differenza di turni sh = shx - shy
e dei segni originali
trovare f
(scorrendo) in modo y*f -> 1
.... dopo che x*f -> x/y
che è il risultato della divisione
spostamento del x*f
indietro di sh
e ripristinare risultato segno (sig=sigx*sigy)
il x*f
può essere calcolato facilmente come questo:
z=1-y
(x*f)=(x/y)=x*(1+z)*(1+z^2)*(1+z^4)*(1+z^8)*(1+z^16)...(1+z^2n)
dove
n = log2(num of fractional bits for fixed point, or mantisa bit size for floating point)
Sto usando questo Divison nei miei bignum
aritmetica, C++ realizzazione di alto livello Divison è come questo:
fixnum fixnum::operator/(const fixnum &x) // return = this/x
{
fixnum u,v,w;
int k=0,s;
s=sig*x.sig; // compute result signum
u=this[0]; u.sig=+1;
v=x; v.sig=+1;
w.one();
while (geq(v,w)) { v=v>>1; k++; } // shift input in range
w=w>>1;
while (geq(w,v)==1) { v=v<<1; k--; }
w.div(u,v); // use divider block
w=w>>k; // shift result back
w.sig=s; // set signum
return w;
}
questo è stato sviluppato nel tempo in cui conta ogni transistor ... quindi dovresti essere in grado di compattarlo con l'uso delle tue unità + e *. spero che sia d'aiuto....
[edit1:] qui è il mio galleggiante attuazione punto
void arbnum::div(const arbnum &x,const arbnum &y,int acc)
{
// O(log(N)*(sqr+mul+inc)) ~ O(1.5*log(N)*(N^2))
// x<y = < 0.5 ; 1 >
// x*f -> x/y , y*f -> 1
int i,nz;
arbnum c,z,q;
c=x;
z.one(); z.sub(z,y); // z=1-y
q=z;
q.inci();
c.mul(c,q); // (x/y)'=x*(1+z)
c._normalize();
nz=z.nfbits();
if (acc<=0) acc=(nz+c.nfbits())<<1;
for (i=int_log2(acc);i>=0;i--)
{
// z.mul(z,z);
z.sqr(z);
nz<<=1; if (nz>acc) nz=acc; z._normalize(nz);
q=z;
q.inci();
c.mul(c,q); // (x/y)'=x*(1+z)*(1+z^2)*(1+z^4)*(1+z^8)*(1+z^16)...
if (i) c._normalize(acc+nz);
}
c._normalize(acc);
overflow();
c.sig=sig;
*this=c;
}
numeri sono:
DWORD *dat; int siz,exp,sig,bits;
dat[siz]
: mantisa MSW = dat[0]
exp
: base 2 esponente di MSB di mantisa
sig
: signum di mantisa
bits
: bit utilizzati di mantisa per velocità fino someoperations
a.inci()
: a++
a.zero
: a=0
a.one
: a=1
a.geq(x,y)
: confronta |x|,|y|
, restituire 0
per |x|<|y|
, 1 > 2 ==
a.add(x,y)
: a=x+y
a.sub(x,y)
: a=x-y
a.mul(x,y)
: a=x*y
a.sqr(x)
: a=x*x
a.nfbits()
: ritorno num di bit frazionari utilizzati in numero (00000100.00011100b -> 6
)
a._normalize()
: normalizzare numero (MSB di mantissa = 1)
a.overflow()
: se rileva che num è ?.111111111111111111111111111111111111111111111b
allora round acc
si desidera la precisione dei bit di mantissa (il mio arbnum ha un numero illimitato di bit di mantissa)
avete un vincolo su quanti cicli può richiedere? –
L'implementazione deve essere conforme allo standard IEEE-754? Che tipo di hardware è questo, ASIC, FPGA, qualcos'altro? Hai consultato la letteratura pertinente, a partire dagli articoli di S. Oberman e P. Soderquist negli anni '90? – njuffa
Non ho un vincolo sul conteggio del ciclo. Vorrei che l'area fosse bassa. Il mio addizionatore è 1 ciclo, il mio moltiplicatore è 1 ciclo. Questo è per un ASIC. Ho consultato alcune pubblicazioni, ma non ho ancora trovato nulla di buono, è per questo che lo sto chiedendo. – Veridian