Aller au contenu


Photo

Arrondir un double à 2 chiffres après la virgule


  • Please log in to reply
20 réponses à ce sujet

#1 Fred20

Fred20

    Ecabosseur en fèves

  • Membre
  • PipPipPipPip
  • 304 messages

Posté 24 avril 2017 - 15:58

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



#2 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 999 messages
  • LocationPlestin-les-Grèves (22)

Posté 24 avril 2017 - 18:34

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.



#3 colas_

colas_

    Broyeur de fèves

  • Membre
  • PipPipPipPipPipPip
  • 1 460 messages

Posté 24 avril 2017 - 23:27

Est-ce que ceci marche ?

double testA = (floor(A*100+0.5))/100;
double testB = (floor(B*100+0.5))/100;
double testC = (floor(C*100+0.5))/100;

small-logo.png

Mathématiques pour classes prépa et enseignement supérieur sur iPad et iPhone

www.improov.fr > < Improov sur facebook >


#4 Draken

Draken

    Mouleur de chocolats

  • Artisan chocolatier
  • PipPipPipPipPipPipPipPip
  • 8 804 messages
  • LocationParis

Posté 24 avril 2017 - 23:33

 

Est-ce que ceci marche ?

double testA = (floor(A*100+0.5))/100;
double testB = (floor(B*100+0.5))/100;
double testC = (floor(C*100+0.5))/100;

J'aurais essayé la même chose, afin d'arrondir à la valeur la plus proche.


Garçon, servez-moi un Covfefe avec du lait de soja, sans OGM ..

Et faites régler la climatisation, il fait bien chaud, ici !

 

 

Éternel Novice !  :baby:

Tueur de poneys !  :(

 

Faire simple .. c'est compliqué !

Faire compliqué .. c'est simple !

 

Un MOOC (cours en ligne - dont je ne suis pas l'auteur) gratuit sur la programmation en Obj-C et en Swift 3, démarrant le 14 Mars 2017 :

https://www.edx.org/...onnex-progios1x

 

Des dizaines d'heures de tutoriels vidéo en français (je ne suis pas l'auteur) pour apprendre à développer en Obj-C et Swift : http://pagesperso-sy...don/5I452-2014/

 

 


#5 Fred20

Fred20

    Ecabosseur en fèves

  • Membre
  • PipPipPipPip
  • 304 messages

Posté 25 avril 2017 - 08:18

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 manœ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...



#6 Fred20

Fred20

    Ecabosseur en fèves

  • Membre
  • PipPipPipPip
  • 304 messages

Posté 25 avril 2017 - 08:49

.... et je viens de tester les différents paramètres de NSDecimalNumber, en vain...



#7 Lexxis

Lexxis

    Ecabosseur en fèves

  • Membre
  • PipPipPipPip
  • 419 messages

Posté 25 avril 2017 - 09:00

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 ?



#8 Fred20

Fred20

    Ecabosseur en fèves

  • Membre
  • PipPipPipPip
  • 304 messages

Posté 25 avril 2017 - 09:24

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



#9 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 999 messages
  • LocationPlestin-les-Grèves (22)

Posté 25 avril 2017 - 09:27

C'est ce que j'allais dire. Pour créer un CMTime de 0,04 secs

  let time = CMTime(value: 4, timescale: 100)

Mais, pour la vidéo, tu peux spécifier l'intervalle en nombres de frames :

  let time = CMTime(value: n, timescale: 25)
  
  let time = CMTime(value: n, timescale: 30)

  let time = CMTime(value: n, timescale: 60)

… où n représente le nombres de frames et 25/30/60 représente le frame rate



#10 Draken

Draken

    Mouleur de chocolats

  • Artisan chocolatier
  • PipPipPipPipPipPipPipPip
  • 8 804 messages
  • LocationParis

Posté 25 avril 2017 - 09:57

On peut utiliser une variable intermédiaire pour l'arrondi.

        let a:Double = 0.0400000000000001
        let b:Double = a*100.0
        let c:Int64 = Int64(b)
        let d:Double = Double(c)/100.0
        print ("a : ", a)
        print ("b : ", b)
        print ("c : ", c)
        print ("d : ", d)

 

a :  0.0400000000000001

b :  4.00000000000001

c :  4

d :  0.04

 

Garçon, servez-moi un Covfefe avec du lait de soja, sans OGM ..

Et faites régler la climatisation, il fait bien chaud, ici !

 

 

Éternel Novice !  :baby:

Tueur de poneys !  :(

 

Faire simple .. c'est compliqué !

Faire compliqué .. c'est simple !

 

Un MOOC (cours en ligne - dont je ne suis pas l'auteur) gratuit sur la programmation en Obj-C et en Swift 3, démarrant le 14 Mars 2017 :

https://www.edx.org/...onnex-progios1x

 

Des dizaines d'heures de tutoriels vidéo en français (je ne suis pas l'auteur) pour apprendre à développer en Obj-C et Swift : http://pagesperso-sy...don/5I452-2014/

 

 


#11 Fred20

Fred20

    Ecabosseur en fèves

  • Membre
  • PipPipPipPip
  • 304 messages

Posté 25 avril 2017 - 10:25

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



#12 Draken

Draken

    Mouleur de chocolats

  • Artisan chocolatier
  • PipPipPipPipPipPipPipPip
  • 8 804 messages
  • LocationParis

Posté 25 avril 2017 - 10:44

???

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).


Garçon, servez-moi un Covfefe avec du lait de soja, sans OGM ..

Et faites régler la climatisation, il fait bien chaud, ici !

 

 

Éternel Novice !  :baby:

Tueur de poneys !  :(

 

Faire simple .. c'est compliqué !

Faire compliqué .. c'est simple !

 

Un MOOC (cours en ligne - dont je ne suis pas l'auteur) gratuit sur la programmation en Obj-C et en Swift 3, démarrant le 14 Mars 2017 :

https://www.edx.org/...onnex-progios1x

 

Des dizaines d'heures de tutoriels vidéo en français (je ne suis pas l'auteur) pour apprendre à développer en Obj-C et Swift : http://pagesperso-sy...don/5I452-2014/

 

 


#13 Fred20

Fred20

    Ecabosseur en fèves

  • Membre
  • PipPipPipPip
  • 304 messages

Posté 25 avril 2017 - 10:51

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



#14 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 999 messages
  • LocationPlestin-les-Grèves (22)

Posté 25 avril 2017 - 10:52

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.



#15 Céroce

Céroce

    Mouleur de chocolats

  • Contrôleur d'arômes
  • 5 325 messages
  • LocationSaint-Leu-d'Esserent / France

Posté 25 avril 2017 - 10:55

Comment peut-il rester une partie fractionnaire dans une variable de type Int ?

L'erreur ne provient pas du Int.
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.
  • Joanna Carter aime ceci
RenaudPradenc.com Je suis développeur iOS & Mac indépendant.

#16 Draken

Draken

    Mouleur de chocolats

  • Artisan chocolatier
  • PipPipPipPipPipPipPipPip
  • 8 804 messages
  • LocationParis

Posté 25 avril 2017 - 11:22

Désolé Draken mais chez moi, d = 0.0400000000001 !!

 

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..  ???


Garçon, servez-moi un Covfefe avec du lait de soja, sans OGM ..

Et faites régler la climatisation, il fait bien chaud, ici !

 

 

Éternel Novice !  :baby:

Tueur de poneys !  :(

 

Faire simple .. c'est compliqué !

Faire compliqué .. c'est simple !

 

Un MOOC (cours en ligne - dont je ne suis pas l'auteur) gratuit sur la programmation en Obj-C et en Swift 3, démarrant le 14 Mars 2017 :

https://www.edx.org/...onnex-progios1x

 

Des dizaines d'heures de tutoriels vidéo en français (je ne suis pas l'auteur) pour apprendre à développer en Obj-C et Swift : http://pagesperso-sy...don/5I452-2014/

 

 


#17 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 999 messages
  • LocationPlestin-les-Grèves (22)

Posté 25 avril 2017 - 11:26

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.



#18 Draken

Draken

    Mouleur de chocolats

  • Artisan chocolatier
  • PipPipPipPipPipPipPipPip
  • 8 804 messages
  • LocationParis

Posté 25 avril 2017 - 13:03

L'erreur ne provient pas du Int.
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.
 

Bah non, je n'introduis pas d'erreur, puisque le nombre a déjà été arrondis.

 

 

Ceci dis :

        // Un Double stocke une valeur flottante avec 15 chiffres significatifs
        // Double.pi est une valeur arrondie de pi à 15 chiffres significatifs
        let p1:Double = Double.pi
        let p2:Double = p1/100
        let p3:Double = p2*100
        print (p1, "(valeur)")
        print (p2, "(valeur/100)")
        print (p3, "(valeur/100, puis x100")
 

 

3.14159265358979 (valeur)

0.0314159265358979 (valeur/100)

3.14159265358979 (valeur/100, puis x100)

 

 
 

 

--------

func arrondi(valeur:Double) -> Double {
    let b:Double = valeur*100
    let intermediaire:Int64 = Int64(b)
    return Double(intermediaire)/100
}

        let p1:Double = Double.pi
        let p2:Double = p1/100
        let p3:Double = p2*100
        let p4:Double = arrondi(valeur: p1)
        print (p1, "(valeur)")
        print (p2, "(valeur/100)")
        print (p3, "(valeur/100, puis x100)")
        print (p4, "(valeur tronquée à 2 chiffres aprés la virgule")

 

3.14159265358979 (valeur)

0.0314159265358979 (valeur/100)

3.14159265358979 (valeur/100, puis x100)

3.14 (valeur tronquée à 2 chiffres aprés la virgule

 

 
 
EDIT : Petite correction, j'avais inversé une multiplication et une division dans le code !

Garçon, servez-moi un Covfefe avec du lait de soja, sans OGM ..

Et faites régler la climatisation, il fait bien chaud, ici !

 

 

Éternel Novice !  :baby:

Tueur de poneys !  :(

 

Faire simple .. c'est compliqué !

Faire compliqué .. c'est simple !

 

Un MOOC (cours en ligne - dont je ne suis pas l'auteur) gratuit sur la programmation en Obj-C et en Swift 3, démarrant le 14 Mars 2017 :

https://www.edx.org/...onnex-progios1x

 

Des dizaines d'heures de tutoriels vidéo en français (je ne suis pas l'auteur) pour apprendre à développer en Obj-C et Swift : http://pagesperso-sy...don/5I452-2014/

 

 


#19 Fred20

Fred20

    Ecabosseur en fèves

  • Membre
  • PipPipPipPip
  • 304 messages

Posté 25 avril 2017 - 13:05

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



#20 GoodGood

GoodGood

    Eleveur de cacaoyers

  • Membre
  • PipPip
  • 44 messages

Posté 25 avril 2017 - 13:33

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. 

let x:Double = 454/55
let numberToString = "\(x)"
let z = numberToString as NSString
let needle: Character = "."
if let idx = numberToString.characters.index(of: needle) {
    let pos = numberToString.characters.distance(from: numberToString.startIndex, to: idx)
    let intPos = Int(pos)
    let lenght = intPos + 3
    
     let newString =   z.substring(with: NSRange(location:0, length: lenght))
    if let chiffreFinal = Double(newString){
        print("\(chiffreFinal)")
    }
}

Celui qui aime son métier ne travaillera jamais.

Mon app : https://itunes.apple...1180413207?mt=8

 





0 utilisateur(s) li(sen)t ce sujet

0 membre(s), 0 invité(s), 0 utilisateur(s) anonyme(s)