Comment puis-je sans risque durée moyenne de deux entiers non signés en C++?

À l'aide de math entier à lui seul, que je voudrais en "toute sécurité" moyenne deux entiers non signés en C++.

Ce que je veux dire par "en toute sécurité" est d'éviter les débordements (et tout ce qui peut être pensé).

Par exemple, avec une moyenne de 200 et 5000, c'est simple:

unsigned int a = 200;
unsigned int b = 5000;
unsigned int average = (a + b) / 2; //Equals: 2600 as intended

Mais dans le cas de 4294967295 et 5000 puis:

unsigned int a = 4294967295;
unsigned int b = 5000;
unsigned int average = (a + b) / 2; //Equals: 2499 instead of 2147486147

Le meilleur que j'ai trouvé est:

unsigned int a = 4294967295;
unsigned int b = 5000;
unsigned int average = (a / 2) + (b / 2); //Equals: 2147486147 as expected

Sont t-il de meilleures façons de faire?

  • Ne pouvez-vous pas jeté la somme de long long?
  • La troisième option de donner la mauvaise réponse, si a et b sont impairs (puisqu'il va s'arrondir vers le bas les deux moitiés).
  • Numéro de brevet AMÉRICAIN 6,007,232. Le calcul de la moyenne de deux nombres entiers arrondi vers zéro en un seul cycle d'instruction: google.com/patents?id=eAIYAAAAEBAJ&dq=6007232 utilise essentiellement return (a >> 1) + (b >> 1) + (a & b & 0x1);
  • ...wow. Je suis sauver ce lien pour la prochaine fois que quelqu'un se plaint à propos des brevets logiciels.
  • il est intéressant de voir comment beaucoup de réponses ci-dessous contiennent cette solution brevetée. Je suis sûr que la plupart d'entre eux n'a développé de façon indépendante, peut-être même sur place pour leur réponse. Qui semble indiquer que le brevet ne répond pas à la norme de non-évidence.
  • c'est un matériel des brevets (notez que le résultat est produit en un seul cycle d'horloge)
  • Je ne suis pas sûr que ce soit une vraie distinction. Le code @ArunSaha a écrit fera le CPU devenir le circuit décrit dans le brevet. Il peut même travailler dans un cycle d'instruction sur un x86, mais je ne suis pas certain. Peu importe, que le code C++ peut être trivialement changé dans le code VHDL, et puis c'est matériel...
  • York: dites-vous ops réponse ne marche pas? il sait. Si votre parler ArunSaha commentaire ou sellibitze réponse, puis vous avez oublié le + (a & b & 0x1) partie.

InformationsquelleAutor Tim | 2010-09-28