IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Problème d'arrondi apres conversion double vers char


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 12
    Points : 8
    Points
    8
    Par défaut Problème d'arrondi apres conversion double vers char
    Bonjour,

    L'objectif est réalisé en deux temps : allocation d'un tableau de pointeur vers des chaines, allocation d'un espace pour allouer un double convertit en caracteres

    Allocation pointeur sur chaine de caractères :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    /**
     * @method utils_addArgToList Permet de creer un tableau de chaine de maniere dynamique,
     * par ajout sucessif d'element
     *
     * @param p_listCol un pointeur vers un tableau de pointeur de chaine de caracteres
     *
     * @param p_sizeList Pointeur sur un int qui contient la taille du tableau pour la reallocation
     *
     * @return Un pointeur vers la zone memoire de l'argument non alloué
     */
     
    - (BOOL)utils_realocList:(char***)p_listCol size:(int**)p_sizeList{
     
      // Si notre tableau d'argument est vide, on l'initialise
      if (*p_sizeList == NULL){
     
        //Alocation d'un pointeur sur un int
        *p_sizeList = malloc(1*sizeof(int));
        //Test l'allocation
        if(*p_sizeList == NULL) free(*p_sizeList);
        else
          {
    	//La taille du tableau est initialisé à zero
    	**p_sizeList=0;
     
    	//Allocation d'un tableau de pointeur sur chaine de caractères, ici de taille 1 pour commencer
    	*p_listCol=malloc(1*sizeof(char*));
     
    	if (*p_listCol == NULL) free (*p_listCol);
    	else
    	  {
    	    return YES;
    	  }
          }
      }else{
        // Le tableau n'est pas vide, on ajoute un argument
        **p_sizeList += 1;
     
        // Realocation du tableau de pointeur vers caractères
        *p_listCol=realloc(*p_listCol,(**p_sizeList + 1)*sizeof(char*));
     
        return YES;
      }
      return NO;
    }
    Allocation de la chaine que l'on va initialiser avec un double :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    - (BOOL)utils_addDoubleToList:(char***)p_listCol withArg:(double)arg size:(int**)p_sizeList{
     
      //On realloue le tableau qui augmente la taille de p_listCol de 1
      if ([self utils_realocList:p_listCol size:p_sizeList]!=NO)
        {
          //Le max de caracteres allouable pour une conversion de double
          char *maxBuffer;
          maxBuffer=calloc(30,sizeof(char));
          //La taille retourné par snprintf, indique ou non la troncature
          int i_len = 0;
     
          if ((i_len = snprintf(maxBuffer,30,"%.15f",arg))>=30){
    	printf("VALEUR DOUBLE TRONQUEE %d / %.15f\n",i_len,arg);
    	free(maxBuffer);
    	return NO;
          }else{
     
    	//On recupere la vrai taille de notre argument
    	int i_sizeArg = strlen(maxBuffer);
    	// On ajoute un element à p_listCol
    	// http://www.postgresql.org/docs/8.1/interactive/datatype.html#DATATYPE-NUMERIC
    	// La taille d'un double avec 15 decimale et un maximum de 30 chiffres 
    	printf("I SIZE ARG = %d\n",i_sizeArg);
    	(*p_listCol)[**p_sizeList]=calloc(i_sizeArg+1,sizeof(char));
    	strcpy((*p_listCol)[**p_sizeList],maxBuffer);
    	printf("ESSAI DE DOUBLE : %s\n",(*p_listCol)[**p_sizeList]);
    	free(maxBuffer);
    	return YES;
          }
        }
     
      return NO;
    }
    Mon problème se trouve dans les arrondi, qui sont mauvais ...
    Ex pour une valeur de 42005100.456840117 j'obtient dans mon buffer caractères

    I SIZE ARG = 24
    ESSAI DE DOUBLE : 42005100.456840120255947

    Soit n'importe quoi :///
    Je comprend pas trop d'ou sorte les chiffres car je fait bien un memset + un calloc (ce qui est déjç redondant me semble t il ..)

    Encore merci pour votre aide,
    Seb

  2. #2
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    Le type double n'est pas magique : sa précision est variable.

    Entre deux puissances de 2 successives, un nombre limité de nombre peuvent être représentés (2**52 pour des doubles 64 bits) (2**52 nombre entre 1 et 2, 2**52 nombre entre 2 et 4, 2**52 entre 2097152 et 4194304...)

    Le nombre 42005100.456840117 n'est pas représentable en double.

    Les doubles les plus proches qui existent sont 42005100.456840120255947 et 42005100.456840112805367 (sur ma machine).
    Tu peux faire le test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <stdio.h>
    #include <math.h>
     
    int main(void)
    {
        size_t i;
        double d = 42005100.45684015;
     
        printf("d: %.15lf\n", d);
        for(i = 0; i < 6; ++i) {
            d = nextafter(d, -1.0);
            printf("d: %.15lf\n", d);
        }
        return 0;
    }
    Si tu veux plus de précision, tu peux peut-être tenter les long double

Discussions similaires

  1. Conversion String vers char
    Par benwit dans le forum Langage
    Réponses: 27
    Dernier message: 30/03/2007, 15h01
  2. Conversion wchar_t ** vers char**
    Par progfou dans le forum C++
    Réponses: 21
    Dernier message: 23/02/2007, 11h12
  3. conversion gchar vers char
    Par shito dans le forum GTK+ avec C & C++
    Réponses: 1
    Dernier message: 16/01/2007, 21h09
  4. Pb de conversion: double[] vers un vector type???
    Par hycsos dans le forum SL & STL
    Réponses: 4
    Dernier message: 15/01/2006, 08h59
  5. [MFC] Problème de conversion CString vers Char *
    Par Darkenshin dans le forum MFC
    Réponses: 10
    Dernier message: 02/12/2005, 15h42

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo