7
votes

Moyen le plus propre de convertir un `double` ou` unique` à `Integer`, sans arrondir

convertir un numéro de point flottant en un entier utilisant CINT ou CTYPE entraînera une fois la valeur de ce nombre. Le int fonction et math.floor peut être utilisé pour convertir un numéro de point flottant en un nombre entier, arrondi vers l'infini négatif, mais les deux fonctionnalités renvoient des valeurs de point flottant qui ne peut pas être utilisé implicitement comme des valeurs entier sans couler.

Y a-t-il une alternative concise et idiomatique à IntTvar = Cint (int (FloatingPointvar)); ? Pascal inclus rond et Trunc Fonctions renvoyées entier ; Y a-t-il un équivalent dans la langue vb.net ou dans le cadre .NET?

Une question similaire, CINT ne ronde pas de double valeur de manière constante - comment puis-je supprimer la partie fractionnée? a été posée en 2011, mais il a simplement demandé s'il y avait un moyen de convertir un numéro de point flottant en un entier; Les réponses ont suggéré un processus en deux étapes, mais cela ne s'est pas entré en profondeur sur ce qui n'existe pas ou n'existe pas dans le cadre. J'aurais du mal à croire que le cadre n'aurait pas quelque chose d'analogue à la Pascal < / a> Trunc La fonction, étant donné qu'une telle chose sera fréquemment nécessaire lors de l'exécution des opérations graphiques à l'aide d'opérandes à virgule flottante [Ces opérations doivent être rendues comme des pixels distincts et doivent être arrondis de manière à ce que ce tour (x) -1 = rond (x-1) pour tous x qui correspond à la plage de +/- (2 ^ 31-1); Même si de telles opérations sont arrondies, elles doivent utiliser le plancher (x + 0,5) plutôt que rond-à-la plus proche, même pour assurer la propriété ci-dessus]

Incidemment, en C # A Typecast à partir de Double à int Utilisation (type) EXPR La notation utilise une sémantique ronde à zéro; Le fait que cela diffère du comportement VB.NET suggère que l'une ou les deux langues utilise ses propres routines de conversion plutôt un opérateur de conversion explicite inclus dans le cadre. Il semblerait probablement que le cadre devrait définir un opérateur de conversion? Un tel opérateur existe-t-il dans le cadre? Qu'est ce que ça fait? Y a-t-il un moyen de l'invoquer de C # et / ou vb.net?


4 commentaires

Ne pas répondre à votre question, tout comme un point de curiosité: convert.toint32 utilise une autre méthode d'arrondi, à savoir l'arrondissement du banquier.


@KonRADRUDOLPH: Merci d'avoir offert cela comme méthode de conversion; C'est malheureusement la même méthode utilisée par cint , bien que le code écrit en C #, cela pourrait être utile.


Ah, j'ai pensé (sans vérifier) ​​que cint a fait rond-point à zéro, plutôt que de troncature ou rond à même. Quoi qu'il en soit, comme je l'ai dit, ce n'est pas une réponse. Je ne peux penser à aucune méthode d'atteinte c # 'S (int) jet d'une étape de VB (qui ne signifie pas qu'il n'y a aucun moyen).


@KonRADRUDOLPH: En fait, ce que j'aimerais, serait rond-à-peu d'infini. Les routines graphiques utilisables à zéro ont souvent une anomalie visible à zéro, et celles qui utilisent des anomalies à deux fois ont parfois des anomalies tous les deux pixels (depuis la séquence (0,5 1,5 2,5 3,5) lorsque l'arrondi devient (0 2 2 4 ). Rond-négatif-Infinity est clairement utile dans de nombreux scénarios; Je me demande si les différentes routines graphiques utilisent leurs propres méthodes internes, ou ce qu'ils font?


4 Réponses :


-4
votes

Vous aurez peut-être besoin d'extraire la partie INT d'un numéro de flotteur:

float num = 12.234;
string toint = "" + num;
string auxil = toint.Split('.');
int newnum = Int.Parse(auxil[0]);


3 commentaires

Je t'en prie, non. N'effectuez pas les opérations arithmétiques en convertissant le numéro à une chaîne et en arrière. Ceci est inefficace, inutile et logiquement convolué.


Comment cela est-il compatible avec le "moyen le plus propre de convertir ..."?


Manière pire et la moins efficace possible.



4
votes

Après une certaine recherche, il semble que VB n'ait pas un moyen propre d'accomplir cela, à écrire une méthode d'extension.

Le C # (int) Cast se traduit directement dans CONV.I4 en IL. VB n'a pas de tels opérateurs et aucune fonction de cadre semble fournir une alternative.

USenet avait Une discussion intéressante sur ce dos en 2005 - bien sûr, beaucoup a changé depuis, mais je pense que cela tient toujours.


12 commentaires

Je me demande pourquoi Microsoft n'aurait-il pas ajouté certaines méthodes à VB ou au cadre dans tout ce temps [et, à ce sujet, comment des routines graphiques gèrent le problème]? Ce n'est pas comme si une conversion non arrondie du point flottant sur des valeurs entières est exactement une opération obscure.


Ils font, en utilisant la fonction correction (). Ma réponse ci-dessous.


@Undefined n ° Le lien dans ma réponse mentionne déjà correction mais mentionne également pourquoi il ne remplit pas l'exigence d'OP. En bref, correction renvoie le type de type et vous toujours besoin de lancer vers entier , identique aux fonctions mentionnées dans la question elle-même.


La coulée n'est pas la question de l'OP, l'arrondi est la question de l'OP. Correction retourne un double, mais c'est un nombre entier, sans arrondir. En substance, un entier.


@Undefined c'est non-sens. Op veut la sémantique de cint (int (x)) (et pas la sémantique de cint (correction (x)) !), Mais plus concis. Le casting est définitivement faisant partie de la question. OP a dit tellement explicitement dans la question et encore dans le commentaire ci-dessous votre réponse.


Je vous référerai au titre: "moyen le plus propre de convertir un double ou unique sur entier , sans arrondir"


Vos propres mots »après une certaine recherche, il semble que VB n'a pas de moyen propre d'accomplir cela, à écrire une méthode d'extension." Mais tu es mal mal, ça fait. C'est mon point.


@Undefined Ok, je vais mordre. Quel voie? Pourquoi ne le montre-tu pas?


Dim Konradrudolph comme double = 0,8 konradrudolph = cint (Fix (konradrudolph) contrairement à votre déclaration, j'ai fourni une "façon propre de l'accomplir ... Aucune méthode d'extension écrite". Le casting est extrêmement standard, une bonne pratique et requis en option Strict. Vous n'êtes pas autorisé à utiliser la conversion implicite sur différents types. Vous devez lancer si vous utilisez l'option stricte, que tout développeur vaut son sel utiliserait toujours.


@Undefinefini, honnêtement, je ne comprends pas pourquoi cela est difficile à comprendre: (1) op veut le résultat dans un entier , pas un double . (2) OP veut une méthode utilisant uniquement l'appel de la fonction one Cast, pas deux . Op explicitement pas envie d'écrire cint (int (x)) (ni cint (fixe (x)) , qui est le même dans le but de cette discussion).


Je ne sais pas pourquoi non plus que vous continuez à y aller de toute façon. Vous avez dit qu'il n'y a pas de moyen. Mais il y a. Je ne me soucie pas si OP veut utiliser le casting ou non, vous devez utiliser le casting avec des options strictes. Pas de choix autrement. Fin de l'histoire.


@Undefinefin "Vous devez utiliser Casting" - Oui, et c'est exactement ce que ma réponse dit. En particulier, ce que ma réponse indique que non la méthode ou l'opérateur VB.NET n'expose directement le code CONV.I4 IL, contrairement à C #, lorsque cette opération est exposée par le (int) Cast.



1
votes

Vous pouvez utiliser le math.trunate code> méthode.

calcule la partie intégrante d'un numéro de point flottant à double précision spécifié. p> blockQuote>

Par exemple: P>

Dim a As double = 1.6666666
Dim b As Integer = Math.Truncate(a) ' b = 1


2 commentaires

math.trunate donne un résultat de type double ; Ce qui précède ne compilera pas sans l'option strict éteint . La fonction int donne le comportement numérique souhaité et irait bien si je voulais utiliser l'option strict éteint , mais ce réglage fait vb.net une langue très originale.


Vous êtes très bien, l'option strict éteinte n'est pas bonne. Je n'ai pas remarqué que mon VS Auto l'a dit comme ça lors de la création d'une demande de console (sinon j'aurais vu un avertissement).



0
votes

Je sais que c'est un vieux cas, mais j'ai vu personne ne suggère la fonction Math.Round ().

Oui Math.Round prend un double et retourne un double. Cependant, il renvoie un nombre arrondi à un nombre entier. Il devrait se convertir facilement et concis en un entier utilisant la cint. Cela suffirait-il?

cint (maths.round (10000.54564)) '= 10001 cint (maths.round (10000.49564)) '= 10000


0 commentaires