Arrotondare il risultato della divisione al numero intero più vicino è pretty simple. Ma sto cercando di arrotondare un risultato della divisione in modo che l'operazione successiva dia la migliore approssimazione. Che è meglio spiegata con una semplice funzione:Round y = x * x al più vicino
const int halfbits = std::numeric_limits<unsigned int>::digits/2;
unsigned x = foo(); // Likely big.
unsigned x_div = x >> halfbits; // Rounded down
unsigned y = x_div * x_div; // Will fit due to division.
posso arrotondare x_div
al più vicino con l'aggiunta di 1<<(halfbits-1)
. Ma poiché x² non è una funzione lineare, y in generale non è arrotondato correttamente. Esiste un modo semplice e più accurato per calcolare (x*x) >> (halfbits*2)
senza utilizzare tipi più grandi?
Penso che l'aggiunta di 3<<(halfbits-3)
a x_div migliora l'arrotondamento, ma non può dimostrare che sia la soluzione migliore. Inoltre, può essere generalizzato per xⁿ?
Modifica: a grande richiesta mi prendo la libertà di "tradurre" la domanda in termini aritmetici puri (nessuna di queste cose che spostano il bit C ...).
Nota: tutte le divisioni successive sono le divisioni di interi, ad esempio 13/3 sarebbe 4.
Problema: non possiamo calcolare x^2 perché x è grande, quindi vorremmo calcolare (x^2)/(2^N).
A questo scopo si calcola
x_div = x/sqrt (2^N)
che poi quadrato:
y = x_div * x_div
Tuttavia, questo risultato è tipicamente breve del valore esatto di (x^2)/(2^N)
e l'OP suggerisce di aggiungere 0,5 * sqrt (2^N) o forse 0,375 * sqrt (2^N) per approssimare meglio il risultato ...
come risposta Oli Charlesworth
come suggerisce c'è un modo molto migliore per arrivare al valore effettivo, pensando a x^2
come (x_hi + x_lo)^2.
Non sono perso con le operazioni di bit, ma potresti forse riformulare le operazioni in modo matematico e meno c centric? Non sto cercando di essere pedante, penso solo che contribuirebbe a chiarire il problema a portata di mano e aiutare a dichiarare il tuo obiettivo. –
Diverse cose da provare: 'x_div_down * x_div_up',' x_div_near * x_div_near'. Se sei disposto a passare il tempo, potresti calcolare '(x_div * x_rest) >> (halfbit-1)' e correggere il risultato. –
Quindi, per essere chiari, impliciti dal tuo '(x * x) >> (halfbits * 2)', in realtà vuoi un risultato accurato a bit * non arrotondato * di quello? O vuoi che il risultato matematico sia arrotondato correttamente? – hyde