Vitesse d'exécution des fonctions ceil(),round(),floor() - page 4

 
Alexey Navoykov:

Donc DBL_EPSILON a 16 décimales :2.2204460492503131e-016

Et dans votre cas, vous en obtenez effectivement un, puisque la différence n'est que de 1e-16, soit 2 fois moins qu'epsilon.


Il fonctionne avec 0.99999999999999999997, mais avec 0.99999999999999999998 il ne fonctionne plus.

 
Nikolai Semko:

Fonctionne avec 0.99999999999999999997, mais avec 0.99999999999999999998 il ne fonctionne plus.


Voici une autre astuce :

Y=(int)(x+1-2*DBL_EPSILON);
Print(Y);                             // 3
Y=(int)(x+1-DBL_EPSILON-DBL_EPSILON);
Print(Y);                             // 4
 

Le nombre 2.2204460492502503131e-016 en notation décimale signifie la résolution du format double (https://msdn.microsoft.com/ru-ru/library/6bs3y5ya(v=vs.100).aspx), ceci

Le plus petit nombre positif x, tel que x + 1,0 n'est pas égal à 1,0.

- est le plus petit nombre positif tel que l'ajout de 1,0 à celui-ci change la valeur du nombre. En d'autres termes, il s'agit de l'erreur relative de la représentation d'un nombre. C'est-à-dire que pour 16 cette limite contiendra tant de neuf décimaux, et pour 64 à la fin elle sera 4 fois plus que 1, et pour 8 moitié moins. Nous devrons donc calculer cette précision afin d'accélérer l'arrondi avec la plus grande précision possible. Il est peu probable que ces calculs soient plus rapides que les performances des fonctions d'arrondi ordinaires. Comme MQL ne permet pas de travailler directement avec les adresses des nombres, nous ne pourrons pas prendre les bits d'un ordre dans le nombre, nous devrons donc inventer l'analogue de la fonction log en base 2. Il est peu probable que cela fonctionne rapidement.

Пределы констант с плавающей запятой
Пределы констант с плавающей запятой
  • msdn.microsoft.com
В следующей таблице представлены ограничения на значения констант с плавающей запятой. Эти ограничения также заданы в стандартном файле заголовка FLOAT.H. Ограничения на константы с плавающей запятой КонстантаЗначениеЗначение Количество цифр q, при котором число с плавающей запятой с q десятичными цифрами можно округлить в представление с...
 
Nikolai Semko:

Voici une autre bizarrerie :

Il s'avère que toute opération mathématique introduit une erreur supplémentaire, qui peut être soit plus soit moins. Par conséquent, en général, comme l'a souligné Vladimir, il est nécessaire de normaliser le résultat.

 

ceil(), floor() ont peu de chance d'être répliqués car le mode d'arrondi du FPU ne peut être contrôlé depuis le µl. La seule chose qui fonctionnera probablement de manière plus ou moins adéquate est round() et elle n'est pas exacte selon la norme. D'ailleurs, c'est à peu près ce à quoi ressemble le round() en forme de C :

double round(double x)
{
    fenv_t save_env;
    feholdexcept(&save_env);
    double result = rint(x);
    if (fetestexcept(FE_INEXACT)) {
        fesetround(FE_TOWARDZERO);
        result = rint(copysign(0.5 + fabs(x), x));
    }
    feupdateenv(&save_env);
    return result;
}
 
Pour comprendre ce que vous voulez arrondir ici, vous devez savoir exactement comment et ce qui est perdu lors de la conversion du format DOUBLE en format INT. Dans ce cas, vous n'obtenez que la partie entière, qui reste après l'arrondi. Par conséquent, tout nombre avec un nombre quelconque de décimales et tout chiffre après la virgule seront supprimés et seule la partie entière reste.
exemple :
2.1758716871 -> (int)2.1758716871 = 2
2.0000000001 -> (int)2.0000000001 = 2
2.9999999999 -> (int)2.9999999999 = 2
c'est ce qu'on appelle la perte de précision lorsqu'un nombre est reformaté.
par conséquent
MathFloor(x)  =  (int)(x)
MathCeil(x)   =  (int)(x)+1;
MathRound(x)  =  (int)(x+0.5)

Sincèrement.
 
Andrey Kisselyov:
Pour comprendre ce que vous voulez arrondir ici, vous devez savoir exactement comment et ce qui est perdu lors de la conversion du format DOUBLE en format INT. dans ce cas, vous n'obtenez que la partie entière, qui reste après la troncature. par conséquent, tout nombre avec un nombre quelconque de décimales et tout chiffre après la virgule seront supprimés et seule la partie entière reste.
exemple:On appelle cela la perte de précision lorsqu'un nombre est reformaté.
par conséquent

Sincèrement.

Pourquoi est-ce si compliqué ?

MathRound(x)  - >  (int)(x)+(int)(2.*(x-(int)(x)));

En quoi est-ce mieux que le modèle plus simple ?

MathRound(x)  ->  (int)(x+0.5);
 
Alexey Navoykov:

Il s'avère que toute opération mathématique introduit une erreur supplémentaire, qui peut être soit plus soit moins. Par conséquent, dans le cas général, comme l'a souligné Vladimir, il est nécessaire de normaliser le résultat.


pavlick_:

Ceil(), floor() ont peu de chances d'être répliqués, car le mode d'arrondi du FPU ne peut pas être contrôlé depuis μl. La seule chose qui fonctionnera probablement de manière plus ou moins adéquate est round() et elle n'est pas exacte selon la norme. D'ailleurs, c'est à peu près à cela que ressemble le round() en forme de C :


Bien sûr, vous avez raison. Mais je vais répéter. Pour 99,9% des tâches, il est absolument correct de remplacer les fonctions d'arrondi par une variante alternative plus rapide utilisant la conversion des types de fraction en (int) ou (long). Un programmeur expérimenté doit simplement être conscient de ce fait et l'appliquer lorsque cela est nécessaire.

Для положительных x:
y=floor(x); -> y=(int)x;
y=ceil(x);  -> y=(int)(x+0.9999999999999997);
y=round(x); -> y=(int)(x+0.5);
 
Nikolai Semko:

Pourquoi est-ce si compliqué ?

En quoi est-ce mieux que le modèle plus simple ?

vous pouvez l'essayer de cette façon.

Nikolai Semko:
Un programmeur expérimenté doit simplement être conscient de ce fait et l'appliquer au moment opportun.

Ce n'est pas qu'il doit, il doit le savoir.

Avec respect.

P.S. Votre formule n'est pas correcte pour l'ensemble des valeurs.
y=ceil(x);  -> y=(int)(x+0.9999999999999997);
voir le mien, j'ai mis à jour le tour à une formule courte, maintenant la liste est complète et entièrement fonctionnelle, utilisez-la.
 
Andrey Kisselyov:


P.S. : votre formule n'est pas vraie pour l'ensemble des valeurs.

voir le mien, j'ai mis à jour le tour à une formule courte, maintenant la liste est complète et entièrement fonctionnelle, utilisez-la.

voir ci-dessus

lorsque x = 3 (n'importe quel nombre entier), il y a une confiture :))