Dlaczego dodawanie 0 do końca literału float zmienia sposób jego zaokrąglania (możliwy błąd GCC)?

Odkryłem na moim x86 VM (32-bitowym) następujący program:

#include <stdio.h>
void foo (long double x) {
    int y = x;
    printf("(int)%Lf = %d\n", x, y);
}
int main () {
    foo(.9999999999999999999728949456878623891498136799780L);
    foo(.999999999999999999972894945687862389149813679978L);
    return 0;
}

Tworzy następujące dane wyjściowe:

(int)1.000000 = 1
(int)1.000000 = 0

Ideone wytwarza również takie zachowanie.

Co robi kompilator, aby tak się stało?

Znalazłem tę stałą, ponieważ śledziłem, dlaczego nie powstał następujący program0 jak się spodziewałem (używając 199s wyprodukował0 Oczekiwałem):

int main () {
    long double x = .99999999999999999999L; /* 20 9's */
    int y = x;
    printf("%d\n", y);
    return 0;
}

Gdy próbowałem obliczyć wartość, przy której wynik przełącza się z oczekiwanego na nieoczekiwany, dotarłem do stałej odpowiedzi na to pytanie.

questionAnswers(4)

yourAnswerToTheQuestion