2009-10-05 5 views
3

Le point flottant IEE754 (64 bits) est censé représenter correctement 15 chiffres significatifs bien que la représentation interne ait 17 bits. Y a-t-il un moyen de forcer les 16ème et 17ème chiffres à zéro?caractères de type double en C++

Ref: http://msdn.microsoft.com/en-us/library/system.double(VS.80).aspx: . . Rappelez-vous qu'un nombre à virgule flottante ne peut approcher qu'un nombre décimal, et que la précision d'un nombre à virgule flottante détermine avec quelle précision ce nombre se rapproche d'un nombre décimal. Par défaut, une valeur Double contient 15 chiffres décimaux de précision, bien qu'un maximum de 17 chiffres soit maintenu en interne. La précision d'un nombre à virgule flottante a plusieurs conséquences: . .

Exemple n °: d1 = 97842111437,390091
d2 = 97.842.111.437,390076
d1 et d2 diffèrent en 16e et 17e positions décimales qui ne sont pas censés être importants. Chercher des moyens de les forcer à zéro. ie d1 = d2 = 97.842.111.437,390000 97842111437,390000

+2

Parlez-vous des flotteurs de 64 bits? Comme dans 15 chiffres décimaux significatifs? – John

+0

Je suis d'accord avec John W. La question est un peu vague. La représentation interne n'est pas du tout décimale. –

+0

IEEE754 double a 52 bits de mantisse: http://en.wikipedia.org/wiki/Double_precision_floating-point_format En dehors d'Intel utilisant des registres à virgule flottante de 80 bits avec 64 bits de mantisse (environ 19 chiffres de résolution), I ' Je n'ai jamais entendu parler de "représentation interne" différente. Pouvez-vous fournir une référence à ce dont vous parlez? – KeyserSoze

Répondre

0

Il faut pouvoir modifier directement les bits dans le numéro en créant une union avec un champ pour le nombre à virgule flottante et un type intégral de la même taille. Ensuite, vous pouvez accéder aux bits que vous voulez et les définir comme vous le souhaitez. Voici dans l'exemple où je frappe le bit de signe; vous pouvez choisir n'importe quel domaine que vous voulez, bien sûr.

#include <stdio.h> 

union double_int { 
    double    fp; 
    unsigned long long integer; 
}; 

int main(int argc, const char *argv[]) 
{ 
    double   my_double = 1325.34634; 
    union double_int *my_union = (union double_int *)&my_double; 

    /* print original numbers */ 
    printf("Float %f\n", my_double); 
    printf("Integer %llx\n", my_union->integer); 

    /* whack the sign bit to 1 */ 
    my_union->integer |= 1ULL << 63; 

    /* print modified numbers */ 
    printf("Negative float %f\n", my_double); 
    printf("Negative integer %llx\n", my_union->integer); 

    return 0; 
} 
+0

Je crois que j'ai mal interprété la question ... eh bien, j'attendrai une clarification puis effacez celle-ci si nécessaire. –

11

N ° Contre-exemple: les deux plus proches nombres à virgule flottante à une

rationnelle
1.11111111111118 

(qui a 15 chiffres décimaux) sont

1.1111111111111799942818834097124636173248291015625 
1.1111111111111802163264883347437717020511627197265625 

En d'autres termes, n'est pas un nombre à virgule flottante qui commence par 1.1111111111111800.

3

Cette question est un peu mal formulée. Le matériel stocke les nombres en binaire et non en décimal. Donc, dans le cas général, vous ne pouvez pas faire mathématiques précises dans la base 10. Certains nombres décimaux (0,1 est l'un d'entre eux!) N'ont pas même avoir une représentation non répétitive en binaire. Si vous avez des exigences de précision de comme ceci, où vous vous souciez du nombre étant de précision connue à exactement 15 chiffres décimaux, vous aurez besoin de pour choisir une autre représentation pour vos nombres.

3

Non, mais je me demande si cela est pertinent pour l'une de vos questions (CCG spécifiques):

GCC Documentation

-ffloat magasin Ne pas stocker les variables à virgule flottante dans les registres, et inhibit les autres options qui peuvent changent si une valeur à virgule flottante provient d'un registre ou d'une mémoire.

Cette option empêche indésirable excès de précision sur des machines telles que le 68000 où les registres flottants (de 68881) conservent une plus grande précision qu'un double est censé avoir. De même pour l'architecture x86. Pour la plupart des programmes, la précision excessive ne fait que du bien, mais quelques programmes reposent sur la définition précise du point flottant IEEE. Utilisez -offloat-store pour ces programmes, après les avoir modifiés pour stocker tous les calculs intermédiaires pertinents en variables.

+1

Bien que l'option de ligne de commande soit spécifique à GCC, le problème ne l'est pas. J'ai utilisé un compilateur C sur les Mac 68030 et 68040 qui avaient des nombres à virgule flottante "étendus", qui n'étaient que des représentations à 80 bits dans les implémentations 68881. –

0

D'une manière générale, les gens ne se soucient que quelque chose comme ça (« Je ne veux que les premiers x chiffres ») lors de l'affichage du numéro. C'est relativement facile avec stringstream s ou sprintf.

Si vous êtes préoccupé par la comparaison des numéros avec ==; vous ne pouvez vraiment pas le faire avec des nombres à virgule flottante. Au lieu de cela, vous voulez voir si les chiffres sont assez proches (par exemple, dans un epsilon() l'un de l'autre).

Jouer directement avec les bits du nombre n'est pas une bonne idée.