Arrondir un double à 2 chiffres après la virgule
Fred20
Membre
Bonjour à tous
Mon sujet peut paraitre ridicule mais je cherche à arrondir un double, mais en vain. J'ai essayé 3 méthodes qui ne marchent pas :
double A = valFloat.doubleValue; //issue de la récupération d'un CTTime d'un currenteTime d'un NSPlayerItem et qui donne 0.04000000000001
double B = 0.04000000000001;
double C = 0.07777777777779;
double testA = (round(A*100))/100;
double testB = (round(B*100))/100;
double testC = (round(C*100))/100;
NSString *test4 = [NSString stringWithFormat:@%.2f,A]; testA = [test4 doubleValue];
NSString *test5 = [NSString stringWithFormat:@%.2f,B]; testB = [test5 doubleValue];
NSString *test6 = [NSString stringWithFormat:@%.2f,C]; testC = [test6 doubleValue];
NSNumberFormatter *fmt = [[[NSNumberFormatter alloc] init]autorelease];
[fmt setMaximumFractionDigits:2];
test4 = [fmt stringFromNumber:[NSNumber numberWithFloat:A]]; testA = [test4 doubleValue];
test5 = [fmt stringFromNumber:[NSNumber numberWithFloat:B]]; testB = [test5 doubleValue];
test6 = [fmt stringFromNumber:[NSNumber numberWithFloat:C]]; testC = [test6 doubleValue];
Des idées pour obtenir respectivement dans un double 0.04, 0.04 et 0.08 ?
Dans l'attente de vous lire et merci d'avance
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Dans un mot, impossible !
Les chiffres "floating point" sont, par défaut, "indistincte"
C"est seulement en les présentant comme strings que l'on puisse avoir la représentation exacte.
Ou, tu peux bidouiller avec NSDecimalNumber, mais je ne vois pas ce que tu gagnerais.
Est-ce que ceci marche ?
J'aurais essayé la même chose, afin d'arrondir à la valeur la plus proche.
Merci Draken pour ta réponse mais je n'ai pas mieux. Voici le résultat :
testA = (double) 0.04000000000000001
testB = (double) 0.04000000000000001
testC = (double) 0.08000000000000002
Et pour répondre à Joanna Carter le but de ma manoe“uvre est d'utiliser ces valeurs pour aller sur une image précise dans une séquence vidéo. Dans cet exemple, l'image 1 est à 0.04 seconde et si j'ai 0.04000000000000001, je passe à l'image 2...d'où mon problème...
.... et je viens de tester les différents paramètres de NSDecimalNumber, en vain...
Il n'y a pas un type de données particulier pour la gestion du temps pour ce qui concerne la vidéo comme CMTime ?
En fait j'avais fait le choix de me déplacer via un slider en prenant comme référence les temps en seconde que j'avais pu récupérer en amont... Bon c'est vrai que j'avais de choix entre les temps en seconde ou les timeValue du CMTime...peut être que mon choix doit se porter plutôt sur les timeValues !!!!
Je vais voir ce que ça donne dans ce sens
Merci en tout cas Lexxis pour ta piste
C'est ce que j'allais dire. Pour créer un CMTime de 0,04 secs
Mais, pour la vidéo, tu peux spécifier l'intervalle en nombres de frames :
... où n représente le nombres de frames et 25/30/60 représente le frame rate
On peut utiliser une variable intermédiaire pour l'arrondi.
Désolé Draken mais chez moi, d = 0.0400000000001 !!
Donc je pense que la piste CMTime reste la meilleure
Je teste et je reviens vers vous
???
Comment peut-il rester une partie fractionnaire dans une variable de type Int ? Je ne vois pas pourquoi un code qui fonctionne en Swift ne le ferais pas en Objective-C.
On peut voir ton code ? tu dois utiliser une formulation compact que le compilateur optimise, en retirant des choses inutiles (à ses yeux).
Je suis bien d'accord avec toi Draken et c'est bien ce qui m'agace...
Quand à mon code, tu l'as au début de ce sujet. Il est simplement placé dans -(void)awakeFromNib
C'est la différence entre les processeurs, etc, pas le langage.
Comme j'ai déjà dit, il n'est jamais possible, de manière fiable, limiter le nombre de chiffres après la virgule.
C'est toi qui introduis l'erreur en divisant par 100, parce que 1/100 n'est pas codable par une somme de puissances de 2.
https://fr.wikipedia.org/wiki/IEEE_754
Les nombres sont toujours stockés en binaire, et le compilateur, la saisie et l'affichage convertissent les nombres décimaux en binaire.
NSDecimalNumber n'a pas ces problèmes, mais il faudra tout de même convertir le NSDecimalNumber en float ou double à un moment donné, alors ça ne règle rien.
La seule bonne réponse est d'utiliser CMTime, qui permet de penser en "frames" plutôt qu'en secondes, et est donc calé précisément. Si ça n'a pas besoin d'être précis à la frame, alors il faut tronquer les chiffres à l'affichage, comme indiqué par Joanna dès sa première réponse.
Et cela ne risque pas de changer ..
Tu utilises TROIS méthodes d'arrondi qui ne fonctionnent pas.
Je t'en propose une QUATRIEME, utilisant une variable intermédiaire de type Int, qui elle fonctionne .
Tu ne l'implémentes pas, tu ne la testes pas.. Tu réutilises ton ancien code et .. oh surprise .. toujours la même erreur ! Et tu en déduis que la méthode 4 ne fonctionne pas.. ???
Moi, je l'ai testé et ça ne plane pas ici. Le moment que l'on utilise un Double ou un Float, les erreurs d'arrondissage arrivent.
Je suis d'accord de Céroce - il faut utiliser le CMTime.
Bah non, je n'introduis pas d'erreur, puisque le nombre a déjà été arrondis.
Ceci dis :
Tout d'abord pout Draken, en effet, si je fais un NSLog, j'ai bien 0.04 qui s'affiche en revanche, si je place un point d'arrêt et que je lis c, j'ai 0.0400000000001.
Par contre compte tenu des arguments de Céroce, je comprends donc mieux la raison de cela et je le rejoins ainsi que Joanna Carter qu'il faut que je travaille plutôt sur CMTime
Merci à tous en tout cas
Salut ,
Voilà ce que j'ai réussi a faire, bon c'est une façon " a l'arache" mais sa a l'air de marcher, par contre il faudra que tu modifie le code pour éviter les craches car je n'ai pas tester toutes les possiblités.
Non, le clé, c'est que NSLog utilise un formatage différent que le débogguer.
Mais, comme dit Fred20, ce n'est pas l'apparence des chiffres qui compte, c'est la valeur en-dessous, qui ne peut jamais être fiable à deux chiffres après la virgule.