Arrondir le résultat de la division à l'entier le plus proche est pretty simple. Mais j'essaie d'arrondir un résultat de division pour que l'opération suivante donne la meilleure approximation. Ce qui est le mieux expliqué par une fonction simple:Arrondi y = x * x au plus proche
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.
Je peux arrondir x_div
à la plus proche en ajoutant 1<<(halfbits-1)
. Mais puisque x² n'est pas une fonction linéaire, y en général n'est pas arrondi correctement. Existe-t-il un moyen simple et plus précis de calculer (x*x) >> (halfbits*2)
sans utiliser de plus grands types?
Je pense qu'ajouter 3<<(halfbits-3)
à x_div améliore l'arrondi, mais ne peut pas prouver que c'est la meilleure solution. Aussi, cela peut-il être généralisé pour xⁿ?
Édition: à la demande générale, je prends la liberté de "traduire" la question en termes purement arithmétiques (aucune de ces choses de décalage en bits C ...).
Note: Toutes les divisions suivantes sont des divisons entières, par exemple 13/3 serait 4.
Problème: Nous ne pouvons pas calculer x^2 parce que x est grand, donc nous aimerions calculer (x^2)/(2^N).
Pour ce faire, nous calculons
x_div = x/sqrt (2^N)
que nous avons ensuite place:
y = x_div * x_div
Cependant, ce résultat est généralement peu de la valeur exacte de (x^2)/(2^N)
et l'OP suggère d'ajouter 0,5 * sqrt (2^N) ou peut-être 0,375 * sqrt (2^N) pour mieux approximer le résultat ...
Comme Oli Charlesworth
La réponse suggère qu'il y a une bien meilleure façon d'arriver à valeur réelle, en pensant à x^2
as (x_hi + x_lo)^2.
Je ne suis pas perdu avec le bit ops, mais pourriez-vous reformuler les opérations d'une manière centrée mathématique et moins centrée? Je n'essaie pas d'être pédant, je pense juste que cela aiderait à éclaircir le problème et aider à définir votre objectif. –
Plusieurs choses à essayer: 'x_div_down * x_div_up',' x_div_near * x_div_near'. Si vous êtes prêt à passer le temps, vous pouvez calculer '(x_div * x_rest) >> (halfbit-1)' et corriger le résultat par cela. –
Donc, juste pour être clair, impliqué par votre '(x * x) >> (halfbits * 2)', vous voulez vraiment * un-arrondi * résultat peu précis de cela? Ou voulez-vous que le résultat mathématique soit arrondi correctement? – hyde