8
votes

Remplacer le système de fonction Delphi.Round

Je viens de découvrir qu'un logiciel que j'ai à réapprocher utilise Extensivelly system.round (). Le problème est que cette fonction utilise "l'arrondissement des banquiers" et le comportement ne peut pas être changé comme dans Math.RoundTo () (RMDown, RMUP, RMNEAIRE, RMTRONCATE).

Je dois changer le comportement en "arrondi normal" (12,5 -> 13 non 12.5 -> 12) ... donc je voudrais remplacer le système.Round () globalement. Je veux faire cela, car rond () est utilisé tant de fois et je ne veux pas les changer tous manuellement.

Comment est-ce possible?


4 Réponses :


14
votes

AVERTISSEMENT : Bien que la réponse ci-dessous traite de la question posée, je recommanderais que personne ne l'utilise jamais. Si vous souhaitez effectuer des arrondies différemment de rond , écrivez et appelez une fonction dédiée.


Vous pouvez utiliser un code de code d'exécution pour modifier l'implémentation de rond .

La ride est que c'est un peu délicat d'obtenir l'adresse de la fonction rond car c'est un intrinsèque. Vous devez également faire attention à suivre la convention appelante utilisée. La valeur d'entrée est transmise dans le registre de pile x87 st (0) et la valeur de retour est un entier 64 bits dans EDX: EAX .

Voici comment le faire. xxx

Si vous préférez implémenter votre version à Pascal que ASM, vous devez adapter la convention d'appel non standard de _round à la convention d'appel standard Delphi. Comme ceci: xxx

Notez que j'ai supposé ici que votre programme cible 32 bits. Si vous devez cibler 64 bits, les principes sont beaucoup les mêmes, mais les détails diffèrent évidemment.


5 commentaires

@Smasher ha, merci! Il y a d'énormes quantités de telles choses. Le code d'exécution à l'accrochage semble toujours intelligent que ce qu'il est vraiment. Le truc avec system_round est quelque chose que j'ai appris de Madshi's Madexcept. Rien d'original ici du tout.


@DavidHeffernan - c'est toujours une connaissance encyclopédique, même si vous ne pensez pas son original


@HUGHJONES: Oui, savoir où trouver les choses que vous avez entendues / lisez à propos d'un excellent atout pour quiconque dans notre profession.


Merci David! Enfin, je devais utiliser le code et changé de rond () sur x: = int (y + 0.5) (cela fonctionne juste pour POS. Numéros!). Mais merci beaucoup pour votre solution de toute façon (marquée comme ma réponse acceptée, car elle répond à ma question intérieure)!


Cela est susceptible d'être trop indiscriminé. Il y aura sûrement d'autres parties d'un programme, peut-être fourni par le code tiers, qui repose sur le comportement intégré de rond . ;)



7
votes
ROUND(12.5) = 13
ROUND(12.1) = 12
ROUND(-12.5)= -13
ROUND(-12.1)= -12

1 commentaires

IMHO C'est la solution la plus simple et la plus propre



1
votes

Vous êtes préoccupé par le temps et les efforts nécessaires pour changer manuellement tous vos appels existants code> code> pour appeler autre chose. Alors ne les changez pas manuellement. Utilisez un outil pour l'automatiser. Par exemple, vous pouvez utiliser SED.

sed -i -e "s/\bRound\b/BiasedRoundAwayFromZero/g" *.pas


7 commentaires

Cela est susceptible d'être trop indiscriminé. Il y aura sûrement d'autres utilisations du mot "rond" dans le code.


Je me demande, ce qui est susceptible d'être plus grand, @David, le nombre de fois le mot autonome rond apparaît dans le code lorsque pas se référant à une fonction, ou le nombre de fois < Code> System.Round est appelé n'importe où dans un programme (pas seulement le code source du projet) et requis pour utiliser le comportement d'arrondi par défaut. Et qui est plus difficile à détecter? Je postule que c'est ce dernier dans les deux cas.


Je pensais plus aux commentaires. Très facile à détecter le système. Très bien sûr. Peu probable d'être d'autres fonctions nommées rondes. Faites attention aux méthodes aussi.


Je suppose qu'avant de remplacer les substitutions, il faut essayer d'obtenir des statistiques à quelle fréquence et dans quelle partie du code qu'il utilise "aléatoire". Je souhaite que Delphi ait été informé de la syntaxe et de remplacer. Ou est-ce appelé "refactoring" peut-être? En général, peut-être que ces doutes sont bloqués, mais je me méfierais également de changer de façon de changer trop de mots, notamment des commentaires, mais également des littéraux de l'interface graphique.


Oui, @arioch, Delphi vient avec une opération de refactorisation de renommée. Je ne suis pas sûr que cela fonctionnerait ici, car je pense que cela reconnaîtra que ce rond est system.round et échoue finalement car il ne peut pas appliquer le changer la déclaration de fonction. Toutefois, si la simple substitution de texte change par inadvertance une autre fonction nommée rond , le refacteur de renommée pourrait facilement revenir le changement après. Combien de littéraux texte d'interface graphique apparaissent dans vos fichiers .PAS, à quelle fréquence utilisez-vous le mot rond en eux, et à quelle vitesse voudriez-vous remarquer si votre interface graphique a dit la mauvaise chose?


@Robkennedy dans mon expérience personnelle avec XE2 Refactoring n'a jamais été aussi fiable. Je soupçonne que c'est basé sur le même analgésique J # défectueux, qui génère tout ce non-sens dans la perspicacité du code et des pannes d'instruction d'erreur. Ps. Mes littéraux graphiques sont principalement en russe, alors ils manquent évidemment «rond» Wourd :-d otoh s'il y aurait une implémentation de protocole de réseau texte ... Eh bien, qui devient spéculative


XE3 Renommer refactorise beaucoup mieux. Je l'utilise beaucoup et avec un bon succès.



0
votes

// banquiers ronds omzeilen xxx


2 commentaires

Bonjour et bienvenue à. Stackoverflow.com est un site anglais. Veuillez toujours fournir des descriptions en anglais à votre code, aux questions et réponses. Votre réponse doit être modifiée pour ne contenir que du texte anglais.


Ce n'est pas ce que l'OP a demandé. Cela ne remplace pas la méthode ronde