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

 
Nikolai Semko:

J'en ai déjà parlé ici.

ok. si je comprends bien, vous écrivez dans ce terminal et dans le cadre de la précision donnée, vous n'êtes pas intéressé par le portage et l'exécution du code sur un autre appareil ou une autre plateforme.

Meilleures salutations.

P.S. Un bon programmeur doit comprendre que le matériel et le programme peuvent changer et que vous devez éviter les bogues à l'avenir.
 
Andrey Kisselyov:
Si vous écrivez dans les limites du terminal donné et dans les limites de sa précision, le portage et le fonctionnement du code sur un autre appareil ou une autre plate-forme ne vous intéressent pas.

Sincèrement.

Exactement. Nous parlons de MQL5 (peut-être aussi de MQL4 - je n'ai pas vérifié). Et le code des classes ou des algorithmes sera parfaitement portable dans MQL. Mais il fonctionnera également en C++. J'ai déjà quelques exemples.

 
Andrey Kisselyov:

P.S. Un bon programmeur doit comprendre que le matériel et le programme peuvent changer et qu'il est nécessaire d'éviter les erreurs à l'avenir. Avec une tâche comme la vôtre, vous ne pourrez peut-être pas trouver facilement une erreur dans une fonction que vous considérerez comme infaillible à ce moment-là.
Dans cette situation, il est impossible d'imaginer les changements dont vous parlez. Qu'est-ce qui pourrait changer dans les mathématiques du calcul de (int)(x+0.5) ? Va-t-il arrêter de rejeter la partie fractionnée ou quoi ?
 
Nikolai Semko:
Dans cette situation, il est impossible d'imaginer les changements dont vous parlez. Qu'est-ce qui peut changer avec les mathématiques du calcul de (int)(x+0.5) ? Va-t-il cesser de laisser tomber la partie fractionnée?

Par exemple, un nouveau type de données sera introduit...

 
STARIJ:

Par exemple, un nouveau type de données sera introduit...

))) Oui, mais le code cessera de fonctionner si l'ancien type de données est annulé.....
 
Je parle de cette pagaille.
y=(int)(x+0.9999999999999997);

Prenons un exemple :
si vous changez même le bitness de la machine, vous passez à 64 bits et la précision de la machine a augmenté, votre formule cessera de fonctionner car la précision de la machine sera beaucoup plus élevée que celle que vous définissez dans votre erreur.

Avec respect.

P.S. il peut y avoir d'autres possibilités où votre formule échouera sur une plage de nombres. erreur d'ajustement constant lors du passage à une autre machine, ou de changements dans le compilateur, dont vous n'êtes pas informé, ou lorsque vous changez la représentation des nombres dans la machine, ou de la découpe d'une partie fractionnaire du nombre lors de la compilation d'une nouvelle version du terminal ... Vous ne savez pas ce qui peut changer, et je ne pense pas que ce soit une bonne idée de faire un IF ou de souffrir pour deviner ce qui va se passer en écrivant une erreur encore et encore...

Je pense que c'est une chose à laquelle il faut réfléchir.

 
Andrey Kisselyov:

...

P.S. Le double par définition ne peut pas être un nombre entier, la représentation d'un nombre dans la mémoire de la machine ne changera pas.

Peut-être êtes-vous en train de dire que double n'est pas un type de données entier, et non pas que vous ne pouvez pas stocker un nombre avec une valeur entière dans une variable de type double? Un double entier peut avoir une valeur entière.

 

J'ai trouvé une explication simple de la différence entre l'arrondi implémenté dans les ordinateurs et la simple troncature post-pile. Quatorze ans, http://delphimaster.net/view/14-10885/all :

Tolik(2003-08-13 11:04) [11].

Ces arrondis sont acceptés en comptabilité. Ainsi, le fisc applique également cet arrondi, de sorte que tout devrait s'additionner, du moins sur le papier :))



DiamondShark(2003-08-13 11:20) [12]

Oh-ho-ho... Encore une fois.
Supposons que nous ayons une distribution de nombres proche de l'aléatoire uniforme. Puis, par arrondi "arithmétique", nous avons :

Le nombre L'incertitude
0 0
1 -1
2 -2
3 -3
4 -4
5 +5
6 +4
7 +3
8 +2
9 +1

Comme on peut facilement le constater, s'il existe un grand nombre de nombres qui doivent ensuite être additionnés (totaux des éléments de documents, soldes de comptes, etc.), l'arrondi "arithmétique" accumulera une erreur systématique avec l'espérance suivante
0,5*10^n * 0,1 * N
où :
n -- poids décimal du chiffre auquel l'arrondi est effectué (à deux chiffres n=-2, à des entiers n=0, etc.)
0,1 est la probabilité de chaque chiffre
N est un nombre d'entiers dans un tableau

Afin d'égaliser les probabilités d'erreur, il est nécessaire de compenser la seule erreur non compensée (voir tableau ci-dessus) +5. Cela se fait en le divisant artificiellement en deux chiffres +5 -5 de probabilité égale, selon la parité du chiffre précédent.

Par ailleurs, il existe une case à cocher dans le mot d'état de la FPU qui contrôle le mode d'arrondi (arithmétique/comptable).


Fin de citation.

Un autre, http://delphimaster.net/view/15-1340952214/all :"car l'utilisateur moyen (gestionnaire/comptable) ne peut pas expliquer pourquoi arrondir 12,5 et 13,5 - donne des résultats différents."


Lorsque l'on donne à l'utilisateur des versions "accélérées" des fonctions d'arrondi, il faut l'avertir qu'elles donnent lieu à une erreur accrue lors de l'addition. Cette erreur devra être soigneusement évaluée dans des situations très différentes. C'est dangereux, il y a une accumulation d'erreurs. J'ai du mal à penser à un exemple où l'arrondi est si important que l'on peut oublier les erreurs qu'il accumule.

Округление чисел. Неужели ТАК правильно???
  • delphimaster.net
3-10545           Kati                  2003-08-12 10:13  2003.09.04   обновление SQL запроса 14-10898          kalishenko            2003-08-14 20:09  2003.09.04   Win2000 Server и доступ в Интернет 1-10692           lww                   2003-08-20 10:30  2003.09.04   Как написать dll для 1С? 1-10813           koks                  2003-08-20...
 

Andrey Kisselyov:
я говорю про вот это безобразие

y=(int)(x+0.9999999999999997);

Très bien, messieurs, vous avez fait votre point. Je vais changer la fonction plafond pour vous :

y=ceil(x);  ->  y=(x-(int)x>0)?(int)x+1:(int)x;
или через дефайн:
#define _ceil(x) (x-(int)x>0)?(int)x+1:(int)x

Cette variante est 25-50% plus lente que la variante :y=(int)(x+0.99999999999997) ; mais elle est maximalement correcte, fonctionne pour les entiers négatifs et est 3 fois plus rapide que ceil(x).

Mais moi-même, en tant que roturier et raté, j'utiliserai la variante avec les neuf, parce que je considère que tous vos arguments sont ennuyeux et que pour moi, qui programme en assembleur depuis longtemps, et qui sait donc ce qui arrive au code après la compilation, c'est trop - de mettre des contrôles là où on peut s'en passer.

 

Une variante pour les nombres positifs et négatifs :

#define _ceil(x) (x-(int)x>0)?(int)x+1:(int)x
#define _round(x) (x>0)?(int)(x+0.5):(int)(x-0.5)
#define _floor(x) (x>0)?(int)x:((int)x-x>0)?(int)x-1:(int)x
Cela semble être un remplacement à part entière de ceil(),round(),floor(), qui donne un avantage de vitesse de 3-4 fois.
Raison: