83 votes

Pourquoi beaucoup de programmes (anciens) utilisent-ils plancher (0,5 + entrée) au lieu de rond (entrée)?

Les différences résident dans la valeur retournée donnant des entrées autour de bris d'égalité-je crois, comme ce code:

int main()
{
    std::cout.precision(100);

    double input = std::nextafter(0.05, 0.0) / 0.1;
    double x1 = floor(0.5 + input);
    double x2 = round(input);

    std::cout << x1 << std::endl;
    std::cout << x2 << std::endl;
}

sorties:

1
0

Mais ils sont tout simplement des résultats différents en fin de compte, on choisit son préféré. Je vois beaucoup de "vieux" programmes C/C++ à l'aide de floor(0.5 + input) au lieu de round(input).

Est-il un historique de la raison? La moins chère sur le CPU?

116voto

haccks Points 33022

std::round est introduit en C ++11. Auparavant, seuls std::floor étaient disponibles, de sorte que les programmeurs les utilisaient.

23voto

Bathsheba Points 23209

Il n'y a pas de raisons historiques, que ce soit. Ce genre de déviance a été autour depuis l'année dot. Folk le font quand ils sont sensation très, très méchant. C'est un grave abus de l'arithmétique à virgule flottante, et bon nombre de professionnels expérimentés programmeurs tomber pour elle. Même le Java bods n'a jusqu'à la version 1.7. Drôle de gars.

Ma conjecture est qu'un décent out-of-the-box allemande de l'arrondissement de la fonction n'a pas été officiellement disponible jusqu'à C++11 (malgré C l'obtention de leur en C99), mais c'est vraiment pas une excuse pour l'adoption de la dite alternative.

Voici la chose: floor(0.5 + input) ne permet pas toujours de retrouver le même résultat que la correspondante std::round appel!

La raison en est très subtil: le point de coupure pour un allemand de l'arrondissement, a.5 pour un entier a est, par une coïncidence de la propriété de l'univers, une dyade rationnelle. Comme cela peut être représentée exactement dans un IEEE754 virgule flottante jusqu'à la 52e puissance de 2, et, par la suite, l'arrondi est un no-op de toute façon, std::round fonctionne toujours correctement. Pour les autres à virgule flottante régimes, consultez la documentation.

Mais l'ajout d' 0.5 d'un double peut introduire une imprécision, ce qui entraîne une légère sous ou de dépassement de certaines valeurs. Si vous pensez à ce sujet, l'ajout de deux double valeurs - qui sont la création de l'involontaire dénaire la conversion et l'application d'une fonction qui est très fort en fonction de l'entrée (comme une fonction d'arrondi), est lié à la fin dans les larmes.

Ne pas le faire.

Référence: Pourquoi les Mathématiques.round(0.49999999999999994) return 1

10voto

Michaël Roy Points 4001

Je pense que c'est là que vous vous trompez:

Mais ils sont tout simplement des résultats différents en fin de compte, on choisit son il préférait. Je vois beaucoup de "vieux" programmes C/C++ à l'aide de plancher(0.5 + d'entrée) au lieu de ronde(entrée).

Ce n'est pas le cas. Vous devez sélectionner le droit d'arrondi régime pour le domaine. Dans une application financière, vous serez tour à l'aide du banquier règles (pas à l'aide du flotteur par la voie). Lors de l'échantillonnage, cependant, arrondi vers le haut à l'aide de static_cast<int>(floor(f + .5)) des rendements moins d'échantillonnage du bruit, ceci augmente la plage dynamique. Lors de l'alignement des pixels, c'est à dire la conversion d'une position à l'écran des coordonnées, à l'aide de toute autre méthode d'arrondi donnera des trous, des lacunes, et d'autres artefacts.

4voto

MivaScott Points 126

Une raison simple pourrait être qu’il existe différentes méthodes pour arrondir les nombres. Ainsi, à moins de connaître la méthode utilisée, vous pouvez obtenir des résultats différents.

Avec floor (), vous pouvez être cohérent avec les résultats. Si le flottant est égal ou supérieur à 0,5, son ajout se répercutera sur le prochain int. Mais .49999 laissera simplement tomber la décimale.

2voto

Barmar Points 135986

De nombreux programmeurs adapter les idiomes qu'ils ont appris lors de la programmation avec d'autres langues. Pas toutes les langues ont un round() de la fonction, et dans ces langues, il est normal d'utiliser floor(x + 0.5) comme un substitut. Lorsque ces programmeurs de démarrage à l'aide de C++, ils ne réalisent pas toujours qu'il y a un haut- round(), ils continuent à utiliser le style auquel ils sont habitués.

En d'autres termes, juste parce que vous voyez beaucoup de code qui fait quelque chose, cela ne veut pas dire il y a une bonne raison de le faire. Vous pouvez trouver des exemples de ce type dans chaque langage de programmation. Souvenez-vous de l'Esturgeon de la Loi:

quatre-vingt-dix pour cent de tout est de la merde

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X