[C] Comportement bizzare float vs double et gettimeofday()

float fige le temps

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Je ne m’explique pas le comportement/bug suivant:

Lorsque ma variable est float le temps ne s’incrémente pas, mais avec double si. Pourquoi?

#include <stdio.h>  // printf
#include <stdlib.h>  // NULL
#include <sys/time.h>  // gettimeofday
#include <unistd.h>  // usleep

void go(void)
{
    struct timeval tv;

    if (gettimeofday(&tv, NULL) != 0)
    {
        printf("gettimeofday() error\n");
        return;
    }

    float t_f = tv.tv_sec;
    double t_d = tv.tv_sec;
    printf("f=%f\n", t_f);
    printf("d=%f\n", t_d);
    printf("\n");
}

int main(void)
{
    go();
    usleep(1.5*1000*1000);
    go();

    return 0;
}

Compilation (centos 7.7.1908 / gcc version 4.8.5 20150623 (Red Hat 4.8.5–39)):

# pour les besoins du projet, je compile en 32 bits, mais en 64 le résultat est le même
$ gcc go.c -Wall -Wextra -m32

Résulat:

$ ./a.out
f=1579515904.000000
d=1579515940.000000

f=1579515904.000000  // meme valeur, wtf
d=1579515941.000000  // +1 sec, tout va bien

Merci d’avance pour votre aide.

(PS: Y’a plus d’IRC sans creation de compte? Smoothirc est mouru, et Freenode et Matrix nécessitent tous les deux un email…)

Tu te demandes pourquoi le temps ne change pas avec un float, mais tu devrais peut-être plus te demander pourquoi le temps en float et en double n’est pas le même. La réalité est qu’un float n’est pas assez précis pour représenter le nombre de secondes depuis 1970. Lors de la conversion du timestamp vers un float, il y a un arrondis qui se passe. Dans ton exemple, 1579515940 et 1579515941 sont tous les deux arrondis en 1579515904.

Si tu lances go() toutes les secondes, le temps en float va éventuellement augmenter d’un coup et "rattraper" le retard qu’il a pris.

Effectivement, j’avais remarqué que le float "sautait" parfois d’une execution à l’autre….

Mais dans ce cas, pourquoi il y a un arrondi et pas un modulo? Quand je fais unsigned char c = 500; j’obtiens la même valeur que int d = 500 % 256;

Tout s’éclaire:

Un float a une mantisse de 23 bits, donc 1579515941 = 0b1011110001001011000000000100101 ne conserve que ses 23 bits haut, et met a zero les autres, soit 0b1011110001001011000000000000000 = 1579515904.

Merci pour l’explication :)

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte